Jdbc核心技术

一、JDBC概述

JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API)。

JDBC接口(API)包括两个层次:
面向应用的API:Java API,抽象接口,供程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
面向数据库的API:Java Driver API,供开发商数据库驱动程序用。

JDBC是sun公司提供的一套用于数据库操作的接口,java程序员只需要面向这套接口编程即可。

不同的数据库厂商,需要针对这套接口。提供不同实现。不同的实现的集合,即为不同数据库的驱动。

​ ——面向接口编程

JDBC程序编写步骤:

二、获取数据库连接

条件1、Driver接口
java.sql.Driver 接口是所有JDBC驱动程序需要实现的接口 。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。
在程序中不需要直接取访问实现了Driver 接口的类,而是由程序驱动管理器类(java.sql.DriverManager)去调用这些Driver实现。
mysql的驱动:com.mysql.jdbc.Driver(mysql6.0及以前)
mysql6.0之后改用:com.mysql.cj.jdbc.Driver

条件2、URL
jdbc URL用于标识一个被注册的驱动程序,驱动程序管理器通过这个URL选择正确的驱动程序,从而建立到数据库的连接。

格式(mysql6.0及以前):

mysql6.0以后需要在后面加上时区:
”jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai“

条件3、用户名和密码

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
public class ConnectionTest {
@Test
public void connectionTest1() throws SQLException {
// 获取Driver实现类对象
Driver driver = new com.mysql.cj.jdbc.Driver();
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
// 将用户名密码封装在Properties中
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "2824199842");
Connection conn = driver.connect(url, info);
System.out.println(conn);
}

@Test // 没有使用第三方的API,使得程序具有更好的移植性
public void connectionTest2() throws Exception{
// 1.使用反射获取Driver实现类对象
Class<?> class1 = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver) class1.newInstance();
// 2.提供要连接的数据库
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
// 3.提供要连接的用户名、密码
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "2824199842");
// 4.建立连接
Connection conn = driver.connect(url, info);
System.out.println(conn);
}

@Test // 使用DriverManager替换Driver
public void connectionTest3() throws Exception {
// 1.获取Driver实现类对象
Class<?> class1 = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver) class1.newInstance();
// 2.提供URL,用户名及密码
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "2824199842";
// 3.注册驱动
DriverManager.registerDriver(driver);
// 4.获取连接
Connection conn = DriverManager.getConnection(url,user,pwd);
System.out.println(conn);
}

@Test // 省略显式加载驱动
public void connectionTest4() throws Exception {
// 提供URL,用户名及密码
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "2824199842";

// 加载Driver mysql的Driver中静态代码块中已经注册了driver
Class<?> class1 = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver) class1.newInstance();
//
// // 注册驱动
// DriverManager.registerDriver(driver);
// 获取连接
Connection conn = DriverManager.getConnection(url,user,pwd);
System.out.println(conn);
}

@Test // 将信息放入配置文件jdbc.properties中,通过读取配置文件获取连接条件(url,user,password,driverclass)
public void connectionTest5() throws Exception {
// 1.读取配置文件信息
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(inputStream);
String user = pros.getProperty("user");
String pwd = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverclass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
Connection conn = DriverManager.getConnection(url,user,pwd);
System.out.println(conn);
}
}

三、使用PreparedStatement实现CRUD

操作和访问数据库:
数据库连接被用于向数据库发送命令和SQL语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。
在java.sql包中有三个接口分别定义了对数据库的不同调用方式:
1、Statement:用于执行静态SQL语句并返回它所生成结果的对象。
2、PreparedStatement:SQL语句被预编译并存储在此对象中,可以用此对象多次高效地执行该语句。
3、CallableStatement:用于执行SQL存储过程。

Statement的弊端:存在拼串操作,并且存在SQL注入问题
PreparedStatement:是Statement的子接口;能最大可能提高性能;操作Blob类型数据;可以防止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
44
45
46
47
48
49
50
51
@Test // 增加记录
public void testInsert() throws Exception {
Connection conn = null;
PreparedStatement ps = null;
try {
// 1.读取配置文件信息
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(inputStream);
String user = pros.getProperty("user");
String pwd = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverclass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
conn = DriverManager.getConnection(url, user, pwd);
System.out.println(conn);
// 4.预编译sql语句,返回PreparedStatement实例
String sql = "insert into customers(name,email,birth)values(?,?,?)";
ps = conn.prepareStatement(sql);
// 5.填充占位符
ps.setString(1, "Taylor");// 索引从1开始
ps.setString(2, "12324@qq.com");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date = sdf.parse("1989-2-22");
ps.setDate(3, new Date(date.getTime()));
// 6.执行操作
ps.execute();
} catch (Exception e) {
// TODO: handle exception
} finally {
try {
// 7.关闭资源
if (ps != null) {
ps.close();
}
} catch (Exception e2) {
// TODO: handle exception
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (Exception e2) {
// TODO: handle exception
e.printStackTrace();
}
}
}

1、可将增加、删除、修改、查询中的共同操作(1.获取连接,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
public class JDBCUtils {
/**
*
* @Description 获取数据库连接
* @author zyz
* @date 2020年3月25日下午5:38:23
* @return
* @throws Exception
*/
public static Connection getConnection() throws Exception {
// 1.读取配置文件信息
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(inputStream);
String user = pros.getProperty("user");
String pwd = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverclass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, pwd);
return conn;
}

/**
*
* @Description // 关闭资源
* @author zyz
* @date 2020年3月25日下午5:40:43
* @param conn
* @param ps
*/
public static void closeResource(Connection conn, Statement ps) {
try {
if (ps != null) {
ps.close();
}
} catch (Exception e2) {
// TODO: handle exception
}
try {
if (conn != null) {
conn.close();
}
} catch (Exception e2) {
// TODO: handle exception
e.printStackTrace();
}
}
}

2、进一步可将增加、删除、修改中的共同操作(1.获取连接,2.预编译sql,3.填充sql,4.执行操作,5.关闭资源)封装到一个方法中。

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
// 将增删改操作写成一个通用的方法
public void update(String sql, Object ... args) {
// 1.建立连接
Connection conn = null;
// 2.预编译sql
PreparedStatement ps = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
// 3.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
// 4.执行操作
ps.execute();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
// 5.关闭资源
JDBCUtils.closeResource(conn, ps);
}
}

@Test // 测试通用的方法
public void testUpdate() {
String sql = "delete from customers where id =?";
try {
update(sql,3);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

查询操作

Java与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
public void testQuery1() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet resultset = null;
try {
// 连接
conn = JDBCUtils.getConnection();
// 预编译sql
String sql = "select id,name,email,birth from customers where id = ?";
ps = conn.prepareStatement(sql);
// 填充占位符
ps.setInt(1, 1);
// 执行操作并返回结果集
resultset = ps.executeQuery();
if (resultset.next()) {// 判断结果集的下一条是否有数据
int id = resultset.getInt(1);
String name = resultset.getString(2);
String email = resultset.getString(3);
Date birth = resultset.getDate(4);
// 将数据封装到一个对象中
Customer customer = new Customer(id, name, email, birth);
System.out.println(customer);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, resultset);
}
}

针对Customer表创建通用的查询方法:

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
public Customer queryCustomers(String sql, Object... args) throws Exception {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
ResultSet resultset = ps.executeQuery();
// 获取结果集中的元数据:ResultSetMetaData
ResultSetMetaData rsmd = resultset.getMetaData();
// 通过ResultSetData 获取结果集中的列数
int column = rsmd.getColumnCount();
// 获取数据并封装到对象中
if (resultset.next()) {
Customer customer = new Customer();
for (int i = 0; i < column; i++) {
// 获取列值
Object columnValue = resultset.getObject(i + 1);
// 获取每个列的列名-----属性
String columnName = rsmd.getColumnName(i + 1);
// 通过反射给属性赋值
// 通过列名获取属性
Field field = Customer.class.getDeclaredField(columnName);
field.setAccessible(true);
// 给属性赋值
field.set(customer, columnValue);
}
return customer;
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
JDBCUtils.closeResource(conn, ps);
}
return null;
}

@Test // 测试通用方法
public void testQueryCustomers() {
try {
String sql = "select id,name,email,birth from Customers where id = ? ";
Customer customer = queryCustomers(sql,12);
System.out.println(customer);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

针对Order表创建通用的查询方法:

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
public class OrderQuery {
public Order orderQuery(String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
// 填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
// 返回结果集
rs = ps.executeQuery();
// 获取结果集元数据(用来修饰结果集的类,提供了结果集的各种属性值)
ResultSetMetaData metaData = rs.getMetaData();
// 获取列数
int columnCount = metaData.getColumnCount();
// 将获取到的结果封装到Order对象中
if (rs.next()) {
Order order = new Order();
// 获取每一列的列值 通过结果集
for (int i = 0; i < columnCount; i++) {
Object columnValue = rs.getObject(i + 1);
// 获取每一列的列名 通过元数据
//String columnName = metaData.getColumnName(i + 1);
// 获取别名
String columnName = metaData.getColumnLabel(i+1);
// 通过反射,将对象指定名columnName的属性赋值为指定的属性columnValue
Field field = Order.class.getDeclaredField(columnName);
field.setAccessible(true);
field.set(order, columnValue);
}
return order;
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps,rs);
}
return null;
}

@Test
public void testOrderQuery() {
try {
String sql = "select order_id orderId,order_name orderName,order_date orderDate from `order` where order_id = ?";
System.out.println(orderQuery(sql, 1));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

通用的查询方法(针对所有的 表):

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
public class Query {
// 返回一条结果
public <T> T query(Class<T> clazz, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
// 填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
// 返回结果集
rs = ps.executeQuery();
// 获取结果集元数据(用来修饰结果集的类,提供了结果集的各种属性值)
ResultSetMetaData metaData = rs.getMetaData();
// 获取列数
int columnCount = metaData.getColumnCount();
// 将获取到的结果封装到Order对象中
if (rs.next()) {
T t = clazz.newInstance();
// 获取每一列的列值 通过结果集
for (int i = 0; i < columnCount; i++) {
Object columnValue = rs.getObject(i + 1);
// 获取每一列的列名 通过元数据(表中的列名与类中的属性名不一致时会报错)
// String columnName = metaData.getColumnName(i + 1);
// 解决方式:获取别名(没有别名时即为列名)
String columnName = metaData.getColumnLabel(i + 1);
// 通过反射,将对象指定名columnName的属性赋值为指定的属性columnValue
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(t, columnValue);
}
return t;
}
} catch (Exception e)
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}

@Test
public void testQuery() {
try {
String sql = "select id,name,email from customers where id = ?";
System.out.println(query(Customer.class, sql, 2));
String sql1 = "select order_id orderId,order_name orderName,order_date orderDate from `order` where order_id = ?";
System.out.println(query(Order.class, sql1, 1));
} catch (Exception e) {
e.printStackTrace();
}
}

// 返回多条结果
public <T> List<T> queries(Class<T> clazz, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
int columnCount = metaData.getColumnCount();
// 将获取到的结果封装到列表中
List<T> list = new ArrayList<T>();
while (rs.next()) {
T t = clazz.newInstance();
// 获取每一列的列值 通过结果集
for (int i = 0; i < columnCount; i++) {
Object columnValue = rs.getObject(i + 1);
// 获取每一列的别名 通过元数据
String columnName = metaData.getColumnLabel(i + 1);
// 通过反射,将对象指定名columnName的属性赋值为指定的属性columnValue
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(t, columnValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}

@Test
public void testOrderQuery() {
try {
String sql = "select order_id orderId,order_name orderName,order_date orderDate from `order` where order_id < ?";
List<Order> orders = queries(Order.class,sql, 4);
orders.forEach(System.out::println);
String sql1 = "select id,name,email from customers where id < ?";
List<Customer> customers = queries(Customer.class, sql1, 10);
customers.forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
}
}
}

四、操作BLOB类型字段

TinyBlob:255字节
Blob:65K
MediumBlob:16M
LongBlob:4G

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
@Test // 向Customers表中添加一条Blob类型数据
public void testInsert() throws Exception {
Connection conn = JDBCUtils.getConnection();
String sql = "insert into customers(name,email,birth,photo) value(?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, "wd");
ps.setObject(2, "wd@qq.com");
ps.setObject(3, "1999-7-20");
FileInputStream in = new FileInputStream(new File("./src/wd1.jpg"));
ps.setBlob(4, in);
ps.execute();
JDBCUtils.closeResource(conn, ps);
}

@Test // 查询customers表中的Blob类型的数据
public void testQuery() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
InputStream in = null;
FileOutputStream out = null;
try {
conn = JDBCUtils.getConnection();
String sql = "select id,name,email,birth,photo from Customers where id=? ";
ps = conn.prepareStatement(sql);
ps.setInt(1, 23);
rs = ps.executeQuery();
if (rs.next()) {
int id = rs.getInt("id");// 既可以写索引,又可以写别名或字段名
String name = rs.getString("name");
String email = rs.getString("email");
Date birth = rs.getDate("birth");
Customer customer = new Customer(id, name, email, birth);
System.out.println(customer);

Blob photo = rs.getBlob("photo");
in = photo.getBinaryStream();
out = new FileOutputStream(new File("./src/wd.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
JDBCUtils.closeResource(conn, ps, rs);
}
}

五、数据库事务

事务:一组逻辑操作单元,使数据由一种状态变换到另一种状态。

事务处理:要么所有的事务都被提交(commit),那么这些修改就被永久的保存下来;要么放弃所作的全部修改,整个事务回滚(rollback)到最初的状态。

JDBC事务处理:
1.数据一旦提交,就不可回滚。
2.DDL操作一旦执行,都会自动提交。
DML默认情况下,一旦执行,就会提交。可通过set autocommit=false 取消DML操作的自动提交。
3.默认关闭连接的时候,自动提交。

JDBC程序中为了让多个SQL 语句作为一个事务执行:
调用Connection 对象的setAutoCommit(false); 以取消自动提交事务
在所有的SQL 语句都成功执行后,调用commit(); 方法提交事务
在出现异常时,调用rollback(); 方法回滚事务

若此时Connection 没有被关闭,还可能被重复使用,则需要恢复其自动提交状setAutoCommit(true)。尤其是在使用数据库连接池技术时,执行close()方法前,建议恢复自动提交状态。

事务的ACID属性:
1.原子性(Atomicity):事务是一个不可分割的工作单位,事务的操作要么都发生,要么都不发生。
2.一致性(Consistency):事务必须使数据库从一个一致状态变换到另外一致状态。
3.隔离性(Isolation):一个事务的执行不能被其他事务干扰。
4.持久性(Durability):一个数据一旦被提交,它对数据库的改变就是永久性的。

数据库并发问题:
脏读:对于两个事务T1、T2,T1读取了已经被T2更新但还没被提交的数据。之后,若T2回滚,T1读取的数据就是无效的。
不可重复读:对于两个事务T1、T2,T1读取了一个字段,然后T2更新了该字段。之后,T1再次读取同一个字段,值就不同了。
幻读:对于两个事务T1、T2,T1从一个表中读了一个字段,然后T2再该表中插入了一些新的行。之后,如果如果T1再次读取同一个表,就会多出几行。

四种隔离级别:隔离级别越高,一致性越好,并发性越弱。

六、DAO及相关实现类

DAO:Data Access Object访问数据信息的类和接口,包括了对数据CRUD(Create、Retrival、Update、Delete),而不包含任何业务相关的信息。
有时也称作:BaseDAO(封装通用方法)
作用:为了实现功能的模块化,更有利于代码的维护和升级。

七、数据库连接池

数据库连接池基本思想:为数据库连接建立一个“缓冲池”,预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕后再放回去。

JDBC的数据库连接池使用javax.sql.DataSource 来表示,DataSource只是一个接口,该接口通常由服务器(Weblogic,WebSphere,Tomcat)提供实现,也有一些开源组织提供实现。

Druid数据库连接池

1
2
3
4
5
6
7
8
9
@Test
public void getConnection() throws Exception {
Properties pros = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
pros.load(is);
DataSource dataSource = DruidDataSourceFactory.createDataSource(pros);
Connection conn = dataSource.getConnection();
System.out.println(conn);
}

配置属性:

八、Apache-DBUtils实现CRUD操作

commons-dbutils 是Apache 组织提供的一个开源JDBC工具类库,封装了增删改查操作。

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
public class QueryRunnerTest {
@Test
public void testInsert() {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection();
String sql = "insert into customers(name,email,birth) value(?,?,?)";
int insertCount = runner.update(conn, sql, "zyz", "zyz@qq.com", "1999-1-1");
System.out.println(insertCount);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, null);
}
}

@Test // BeanHandler是ResultSetHandler接口的一个实现类,用于封装表中的一条记录
public void testQuery1() {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection();
String sql = "select id,name,email,birth from customers where id = ?";
BeanHandler<Customer> handler = new BeanHandler<Customer>(Customer.class);
Customer customer = runner.query(conn, sql, handler, 2);
System.out.println(customer);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, null);
}
}

@Test // BeanListhandler是ResultSetHandler接口的一个实现类,用于封装表中的多条记录构成的集合
public void testQuery2() {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection();
String sql = "select id,name,email,birth from customers where id > ?";
BeanListHandler<Customer> handler = new BeanListHandler<Customer>(Customer.class);
List<Customer> customers = runner.query(conn, sql, handler, 2);
customers.forEach(System.out::println);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, null);
}
}

@Test // 查询特殊值
public void testQuery3() {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection();
String sql = "select count(*) from customers";
ScalarHandler handler = new ScalarHandler();
Long count = (Long) runner.query(conn, sql, handler);
System.out.println(count);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, null);
}
}
}