14.Jdbc

Jdbc

1.概述

1.JDBC为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题
2.Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作
3.java利用Jdbc规定一套接口规范,让不同的数据库厂商实现,在java程序中直接调用接口的方法即可,java程序员直接面对接口编程即可
4.JDBC相关类和接口在java.sql和javax.sql包中

1.1总体步骤

(1) 加载驱动 -- 加载Driver 类
(2) 获取连接 -- connection
(3) 写sql语句 -- CRUD
(4) 释放资源-- close
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
mport java.sql.*;
import java.util.Properties;
import java.util.logging.Logger;
import com.mysql.jdbc.Driver;

//完成简单的操作
//方式1:会直接使用com.mysql.jdbc.Driver()属于静态加载,灵活性差,依赖强
public class jdbc01 {
public static void main(String[] args) throws SQLException {
//前置工作:导入mysql的jar文件拷贝到路径下
//1.注册驱动
Driver driver = new Driver();

//2.得到连接
//jdbc:mysql://规定好表示协议,通过jdbc的方式连接mysql
String url = "jdbc:mysql://127.0.0.1:3306/haozi";
Properties properties = new Properties();
//将用户名和密码放入到properties对象
properties.setProperty("user","root");
properties.setProperty("password","5399joker");
Connection connect = driver.connect(url, properties);

//3.执行sql语句
String sql = "insert into test1 values(1,'耗子',18)";
Statement statement = connect.createStatement();
int rows = statement.executeUpdate(sql); //如果是 dml语句,返回的就是影响行数
System.out.println(rows>0? "成功":"失败");

//4.关闭连接
statement.close();
connect.close();

}
}

2.连接数据库的五种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import com.mysql.jdbc.Driver;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcConn {
@Test
//第一种
public void connect01() throws SQLException {
Driver driver = new Driver();
//2.得到连接
//jdbc:mysql://规定好表示协议,通过jdbc的方式连接mysql
String url = "jdbc:mysql://127.0.0.1:3306/haozi";
Properties properties = new Properties();
//将用户名和密码放入到properties对象
properties.setProperty("user","root");
properties.setProperty("password","5399joker");
Connection connect = driver.connect(url, properties);
System.out.println(connect);
}
//第二种
@Test
public void connect02() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用反射加载Driver类,动态加载,更加的灵活,减少依赖性
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
String url = "jdbc:mysql://127.0.0.1:3306/haozi";
Properties properties = new Properties();
//将用户名和密码放入到properties对象
properties.setProperty("user","root");
properties.setProperty("password","5399joker");
Connection connect = driver.connect(url, properties);
System.out.println(connect);
}
//第三种
@Test
public void connect03() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用DriverManager代替Driver进行统一管理
//使用反射加载Driver类
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
//创建url和user和passwd
String url = "jdbc:mysql://127.0.0.1:3306/haozi";
String user = "root";
String password = "5399joker";
//注册Driver驱动
DriverManager.registerDriver(driver);
//利用DriverManager进行读取
//拿到连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
//第四种,推荐使用~~~~
@Test
public void connect04() throws ClassNotFoundException,SQLException{
//使用Class.forName自动完成注册驱动,简化代码
//使用反射加载了Driver类
Class.forName("com.mysql.jdbc.Driver");
//创建url和user和passwd
String url = "jdbc:mysql://127.0.0.1:3306/haozi";
String user = "root";
String password = "5399joker";
Connection connection =DriverManager.getConnection(url,user,password);
System.out.println(connection);
}
//第五种,在第四种的方式上改进,增加配置文件,让连接mysql更灵活
@Test
public void connect05() throws IOException, ClassNotFoundException, SQLException {
//使用配置文件,连接数据库更灵活
//通过Properties对象获取配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Connection connection = DriverManager.getConnection(url,user,password);
System.out.println(connection);
}
}

3.ResultSet(结果集)

1.表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
2.ResultSet对象保持一个光标指向其当前的数据行,最初,光标位于第一行之前
3.next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

//演示select语句返回ResultSet,并取出结果
public class ResultSet_ {
public static void main(String[] args) throws IOException, SQLException {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
//得到链接
Connection connection = DriverManager.getConnection(url,user,password);
//得到Statement
Statement statement = connection.createStatement();
//组织sql语句
String sql = "select id,name,age from test1";
//执行给定的sql语句,该语句返回单个ResultSet对象
ResultSet resultSet = statement.executeQuery(sql);
//使用while取出数据
while (resultSet.next()){ //resultSet.next()让光标向后移动,如果没有更多行,则返回false
int id = resultSet.getInt(1);
String name = resultSet.getNString(2);
int age = resultSet.getInt(3);
System.out.println(id+"\t"+name+"\t"+age);
}
//关闭连接
resultSet.close();
statement.close();
connection.close();

}
}

4.SQL注入

1.Statement对象用于执行静态SQL语句并返回其生成的结果的对象
2.在连接建立后,需要对数据库进行访问,执行命令或是SQL语句,可以通过
Statement [存在SQL注入]
PreparedStatement [预处理]
CallableStatement [存储过程]
3.Statement对象执行SQL语句,存在SQL注入风险
4.要防范SQL注入,只要用PreparedStatement(从Statement扩展而来)取代Statement就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//Statement演示sql注入
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

//演示statement的注入问题
public class Statement_ {
public static void main(String[] args) throws IOException, SQLException {
Scanner sc = new Scanner(System.in);
//让用户输入管理员用户名和密码
System.out.print("请输入管理员的名字:");
String admin_name = sc.nextLine();
//如果希望看到SQL注入,这里需要用nextLine,next()方法时当接收到空格或单引号则判定为输入结束
System.out.print("请输入管理员的密码:");
String admin_passwd = sc.nextLine();

//通过Properties对象获取配置文件信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Connection connection = DriverManager.getConnection(url,user,password);
Statement statement = connection.createStatement();
String sql = "select name,pwd from admin where name ='"
+admin_name+"'and pwd = '"+admin_passwd+"'";
ResultSet resultSet = statement.executeQuery(sql);
if(resultSet.next()){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
resultSet.close();;
statement.close();;
connection.close();
}
}
//输入用户名:1' or
//输入密码:or '1'= '1
//然后会发现登陆成功

5.PreparedStatement预处理

1.PreparedStatement执行的SQL语句中的参数用问号来表示,调用PreparedStatement对象的setXxx()方法来设置这些参数,setXxx()方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从1开始),第二个是设置的SQL语句中的参数的值
2.调用excuteQuery()返回ResultSet对象
3.调用excuteUpdate()执行更新,包括增、删、修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

//演示preparedstatement使用
public class PreparedStatement_ {
public static void main(String[] args) throws IOException, SQLException {
Scanner sc = new Scanner(System.in);
//让用户输入管理员用户名和密码
System.out.print("请输入管理员的名字:");
String admin_name = sc.nextLine();
//如果希望看到SQL注入,这里需要用nextLine,next()方法时当接收到空格或单引号则判定为输入结束
System.out.print("请输入管理员的密码:");
String admin_passwd = sc.nextLine();

//3.通过Properties对象获取配置文件信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Connection connection = DriverManager.getConnection(url,user,password);
//3.1sql语句的问号相当于占位符
String sql = "select name,pwd from admin where name = ? and pwd = ? ";
//3.2得到PrepareStatement
//3.2preparedStatement 对象实现了 PreparedStatement接口的实现类的对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//3.3给?赋值
preparedStatement.setString(1,admin_name);
preparedStatement.setString(2,admin_passwd);

//执行select语句使用excuteQuery,执行dml(update,insert,delete) executeUpdate()查找操作用
//这里执行查询的时候不用再写sql了
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
resultSet.close();
preparedStatement.close();
connection.close();
}
}
//可以抑制SQL注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//通过预处理实现增删改查
public class PreparedStatementDML_ {
public static void main(String[] args) throws IOException, SQLException {
Scanner sc = new Scanner(System.in);
//让用户输入管理员用户名和密码
System.out.print("请输入ID:");
String admin_ID = sc.nextLine();

System.out.print("请输入管理员的名字:");
String admin_name = sc.nextLine();

//如果希望看到SQL注入,这里需要用nextLine,next()方法时当接收到空格或单引号则判定为输入结束
System.out.print("请输入管理员的密码:");
String admin_passwd = sc.nextLine();

//3.通过Properties对象获取配置文件信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Connection connection = DriverManager.getConnection(url,user,password);
//3.1sql语句的问号相当于占位符
String sql = "insert into admin values (?,?,?)";
//3.2得到PrepareStatement
//3.2preparedStatement 对象实现了 PreparedStatement接口的实现类的对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//3.3给?赋值
preparedStatement.setString(2,admin_name);
preparedStatement.setString(1,admin_ID);
preparedStatement.setString(3,admin_passwd);

//执行select语句使用excuteQuery,执行dml(update,insert,delete) executeUpdate()查找操作用
//这里执行查询的时候不用再写sql了
//4.执行dml语句,返回值为受影响的行数
int rows = preparedStatement.executeUpdate();
System.out.println(rows>0?"执行成功":"执行失败");
//关闭连接
preparedStatement.close();
connection.close();
}
}

6.通过自定义的JDBCUtils工具包来操作数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//JDBCUtils工具包
//工具类,完成mysql的连接和关闭
public class JDBCUtils {
//定义相关属性(4个),因为只需要一份,所以做出static
private static String user; //用户名
private static String password; //密码
private static String url; //url
private static String driver; //驱动名

//在static代码块去初始化
static {
try {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//读取数据属性值
user =properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
driver = properties.getProperty("driver");
}catch (IOException e) {
//再实际开发者中,我们可以这样处理,把编译异常改成了运行异常,调用者可以选择捕获异常,也可以选择默认处理该异常,比较方便
throw new RuntimeException(e);
}
}
//连接数据库,返回Connection
public static Connection getConnection(){
try{
return DriverManager.getConnection(url,user,password);
}catch (SQLException e){
throw new RuntimeException(e);
}
}
//关闭连接,如果需要关闭资源就传入对象,否则为空null
public static void close(ResultSet set, Statement statement,Connection connection){
//判断是否为空
try {
if (set != null) {
set.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
}catch (SQLException e){
throw new RuntimeException(e);
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//实现案例
//演示如何使用JDBCUtils工具类,实现dml和select语句
public class JDBCUtils_Use {
public static void main(String[] args) {
//测试

}
@Test
public void testSelect(){
Connection connection = null;
PreparedStatement preparedStatement=null;
ResultSet set = null;
String sql = "select * from test1";
try {
connection = JDBCUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
set = preparedStatement.executeQuery();
//遍历结果
while (set.next()){
int id = set.getInt("id");
String name = set.getString("name");
int age = set.getInt("age");
System.out.println(id+"\t"+name+"\t"+age);
}
}catch (SQLException e){
e.printStackTrace();
}finally {
JDBCUtils.close(set,preparedStatement,connection);
}
}
@Test
public void testDML(){
//1.得到连接
Connection connection = JDBCUtils.getConnection();
//2.组织一个sql语句
PreparedStatement preparedStatement = null;
String sql = "update test1 set name = ? where id = ?";
//3.创建一个prepareStatement对象
try {
preparedStatement = connection.prepareStatement(sql);
//给占位符
preparedStatement.setString(1,"强子");
preparedStatement.setInt(2,1);
//执行
preparedStatement.executeUpdate();
}catch (SQLException e){
e.printStackTrace();
}finally {
//关闭资源
JDBCUtils.close(null,preparedStatement,connection);
}
}
}

7.事务

1.JDBC程序中当一个Connection对象创建时,默认下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚
2.JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务
3.调用Connection的setAutoCommit(false)可以取消自动提交事务
4.再所有的SQL语句都成功执行后,调用Connection的commit();方法提交事务
5.通过调用Connection的rollback();方法回滚事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//经典案例之转账
//JDBC中如何使用事务
public class Transaction_ {
@Test
//没有使用事务
public void noTransaction(){
//1.得到链接
Connection connection = null; //在默认情况下,connection对象是默认自动提交
//2.组织一个sql
String sql1 = "update account set balance = balance -100 where id = 1";
String sql2= "update account set balance = balance +100 where id = 2";
PreparedStatement preparedStatement = null;
try{
//得到连接
connection = JDBCUtils.getConnection();
preparedStatement = connection.prepareStatement(sql1);
//执行
preparedStatement.executeUpdate();
int i = 1/0;//抛出异常
preparedStatement = connection.prepareStatement(sql2);
//执行
preparedStatement.executeUpdate();
}catch (SQLException e){
e.printStackTrace();
}finally {
JDBCUtils.close(null,preparedStatement,connection);
}
}
//使用事务来解决问题
@Test
public void useTransaction(){
//1.得到链接
Connection connection = null;
//2.组织SQL文件
String sql1 = "update account set balance = balance -100 where id = 1";
String sql2= "update account set balance = balance +100 where id = 2";
//3.创建preparedStatement对象
PreparedStatement preparedStatement = null;
try{
connection = JDBCUtils.getConnection();//在默认情况下,connection是默认自动提交
//将 connection 设置为不自动提交
connection.setAutoCommit(false); //开启事务
preparedStatement = connection.prepareStatement(sql1);
preparedStatement.executeUpdate(); //执行sql1

//int i = 1/0;//抛出异常
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate(); //执行sql2


//这里提交事务
connection.commit();
}catch (SQLException e){
//这里我们可以进行回滚,即撤销执行的SQL
//connection.rollback();默认回滚到事务开始状态
System.out.println("执行发生了异常,撤销执行的sql");
try {
connection.rollback();
}catch (SQLException throwables){
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
//关闭资源
JDBCUtils.close(null,preparedStatement,connection);
}
}
}

8.批处理

1.当需要成批插入或者更新记录时,可以采用java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理,通常情况下比单独提交处理更有效率
2.JDBC的批量处理语句包括下面方法:
2.1addBatch():添加需要批量处理的SQL语句或参数
2.2executeBatch():执行批量处理语句
2.3clearBatch();清空批处理包的语句
3.JDBC连接MySQL时,如果要使用批处理功能,请再url中添加参数?rewriteBatchedStatements=true;
4.批处理往往和PreparedStatement一起搭配使用,既可以减少编译次数,又减少运行次数,效率大大提高

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//演示java的批处理
public class Batch_ {


//传统方法添加500条数据
@Test
public void noBatch() throws Exception{
Connection connection = JDBCUtils.getConnection();
String sql = "insert into admin2 values(null,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 0;i<500;i++){
preparedStatement.setString(1,"jack"+i);
preparedStatement.setString(2,"666");
preparedStatement.executeUpdate();
}
long end = System.currentTimeMillis();
System.out.println("耗时"+(end-start));
//关闭连接
JDBCUtils.close(null,preparedStatement,connection);

}
//使用批量方式添加数据
@Test
public void batch() throws Exception{
Connection connection = JDBCUtils.getConnection();
String sql = "insert into admin2 values(null,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 0;i<500;i++){
preparedStatement.setString(1,"jack"+i);
preparedStatement.setString(2,"666");
//将sql语句加入到批处理包中 ->
preparedStatement.addBatch();
//当有400条记录时,再批量执行
if((i+1)%100 ==0){
preparedStatement.executeBatch();
//清空一把
preparedStatement.clearBatch();
}
}
long end = System.currentTimeMillis();
System.out.println("批量方式耗时"+(end-start));
//关闭连接
JDBCUtils.close(null,preparedStatement,connection);
}
}

9.数据库连接池

1.传统的JDBC数据库连接使用DriverManager来获取,每次获取连接的时候都要将Connection加载到内存,在验证,频繁的连接数据库会占用很多系统资源,容易造成崩溃
2.每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄漏
3.传统的连接方式不能控制创建连接的数量
4.解决可以使用数据库连接池技术(connection pool)
5.预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从”缓冲池”中取出一个,使用完毕后再放回去
6.数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
7.当出现很多请求连接数据库时,这些请求将被加入到等待队列

9.1连接池种类

1.JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方提供实现
2.C3P0数据库连接池,速度相对较慢,稳定性不错(hibernate,spring)
3.DBCP数据库连接池,速度相对C3p0较快,但不稳定
4.Proxool数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
5.BoneCP数据库连接池,速度快
6.Druid(德鲁伊)是阿里提供的数据库连接池,很多优点,推荐用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//C3P0连接实例
public class C3P0_ {
//方式1:相关参数,在程序中指定user、url、password等
@Test
public void testC3P0_01() throws Exception{
//1.创建一个数据源对象
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
//2.通过配置文件mysql.properties获取相关的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("drover");
//给数据源 combo……设置相关参数
//连接的管理是由combo……来管理的
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);

//设置初始化连接数
comboPooledDataSource.setInitialPoolSize(10);
//设置最大连接数
comboPooledDataSource.setMaxPoolSize(50);
//这个方法就是从datasource接口实现的
Connection connection = comboPooledDataSource.getConnection();
System.out.println("连接成功");
}
}

10.德鲁伊连接池

1
2
3
4
5
6
7
8
9
10
配置文件
key=vlaue
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/haozi?rewriteBatchedStatements=true
username=root
password=5399joker
initialSize=10
minIdle=5
maxActive=50
maxWait=5000
1
2
3
4
5
6
7
8
9
10
public void testDruid() throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\Druid-config.perproties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();
System.out.println("连接成功");
connection.close();


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
配置文件
//基于druid数据库连接池的工具类
public class JDBCUtilsByDruid {

private static DataSource ds;
//在静态代码块完成ds初始化
static {
Properties properties = new Properties();
try{
properties.load(new FileInputStream("src\\Druid-config.perproties"));
ds = DruidDataSourceFactory.createDataSource(properties);
}catch (Exception e){
e.printStackTrace();
}

}
//编写getConnection方法
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
//关闭连接
public static void close(ResultSet resultSet, Statement statement,Connection connection){
try{
if (resultSet!=null){
resultSet.close();
}
if (statement!=null){
statement.close();
}
if (connection!=null){
connection.close();
}
}catch (SQLException e){
throw new RuntimeException(e);
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//德鲁伊工具类
public void testSelect(){
Connection connection = null;
String sql = "select * from test1 where id = ?";
PreparedStatement preparedStatement = null;
ResultSet set = null;
try {
connection = JDBCUtilsByDruid.getConnection();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,1);
set = preparedStatement.executeQuery();
while (set.next()) {
int id = set.getInt("id");
String name = set.getString("name");
int age = set.getInt("age");
System.out.println(id + "\t" + name + "\t" + age);
}
}catch(SQLException e){
e.printStackTrace();
}finally {
JDBCUtilsByDruid.close(set,preparedStatement,connection);
}
}

11.DBUtils

1.是Apache组织提供的一个开源JDBC工具类
2.DbUtils类
2.1 QueryRunner类:该类封装了SQL的执行,是线程安全的,可以实现增、删、改、查、批处理
2.2使用QueryRunner类实现查询
2.3ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按要求转换成另一种形式
图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Actor文件
package JDBC.datasource;



//Actor对象和test1表的记录对应
public class Actor {

private Integer id;
private String name;
private Integer age;

public Actor(){

}
public Actor(Integer id,String name,Integer age){ //一定要给一个无参构造器[反射需要]
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

@Override
public String toString() {
return "\nActor{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//用DBUtils+数据库连接池(德鲁伊)方式,完成对表test1的增删改查
public class DBUtils_USE {


//使用apache-DBUtils工具类+druid(德鲁伊)完成对表的增删改查工作
@Test
public void testQueryMany() throws SQLException { //返回结果是多行的情况
//1.得到连接(druid)
Connection connection = JDBCUtilsByDruid.getConnection();
//2.使用DBUtils类和接口,先引进DBUtils相关的jar,加入到本项目
//3.创建QueryRunner
QueryRunner queryRunner = new QueryRunner();
//4.就可以执行相关的方法,返回ArrayList结果集
String sql = "select * from test1 where id >= ?";
/*
* queryRunner,执行查询,得到resultset ------>封装到------>ArrayList 集合中
* 返回集合
* connection:连接
* sql:执行的sql语句
* new BeanListHandler<>(Actor.class):在将resultset --> 取出到actor对象,然后封装到ArrayList中
* 1:就是给sql语句中的?赋值,可以有多个,因为是可变参数
* */
List<Actor> list =
queryRunner.query(connection,sql,new BeanListHandler<>(Actor.class),1);
for (Actor actor:list){
System.out.println(actor);
}

//释放资源
JDBCUtilsByDruid.close(null,null,connection);

}
//返回单行数据
@Test
public void testQuerySingle() throws SQLException {
System.out.println("使用druid方式完成");
//1.得到连接
Connection connection = JDBCUtilsByDruid.getConnection();
//2.使用DBUtils类和接口,先引入DBUtils相关的jar,加入到本地项目
QueryRunner queryRunner = new QueryRunner();
String sql = "select * from test1 where id = ?";

Actor query = queryRunner.query(connection, sql, new BeanHandler<>(Actor.class), 1);
System.out.println(query);


JDBCUtilsByDruid.close(null,null,connection);
}


//演示apache-dbutils + druid完成查询结果是单行单列-返回的就是object
@Test
public void Scalar() throws SQLException {
Connection connection = JDBCUtilsByDruid.getConnection();
QueryRunner queryRunner = new QueryRunner();
String sql = "select name from test1 where id = ?";

Object query = queryRunner.query(connection, sql, new ScalarHandler(), 1);
System.out.println(query);

JDBCUtilsByDruid.close(null,null,connection);
}

//实现增删改查
@Test
public void testDML() throws SQLException {
Connection connection = JDBCUtilsByDruid.getConnection();
QueryRunner queryRunner = new QueryRunner();
String sql = "update test1 set name = ? where id = ?";
String sql2 = "insert into test1 values(null,?,?)";
String sql3 = "delete from test1 where id = ?";

//queryRunner.update:更新数据,返回值为改动的行数
int affectedRow = queryRunner.update(connection,sql3, 3);
System.out.println(affectedRow);

JDBCUtilsByDruid.close(null,null,connection);
}
}

12.BasicDao

1.apache-dbutils+Druid简化了JDBC开发,但还有不足
1.1SQL语句是固定的,不能通过参数传入,通用性不好
1.2对于select操作,如果有返回值,返回类型不能固定,需要使用泛型
1.3将来的表很多,业务需求复杂,不可能只靠一个java类完成
图片

1
//代码在本地src//Dao_包下

14.Jdbc
http://example.com/2023/03/20/java/14.JDBC/
作者
haozi0o0
发布于
2023年3月20日
许可协议