JDBC实现增删改查学习笔记
一、Statement简介
在java.sql包中3个接口分别定义了对数据库的调用的不同方式:
- (1)Statement:用于执行静态SQL语句并返回它所生成的结果的对象
- (2)PrepareStatement:SQL语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句
- (3)CallableStatement:用于执行SQL存储过程
注意: Satement是对SQL语句进行拼接,容易被钻漏洞(SQL注入)。所以一般会用PreparedStatement来代替Statement
- PreparedStatement是Statement的子接口,是预编译的的Statement
二、实现增删改操作
- 四种对数据库的操作,可以分为两类:增删改、查
- 增删改:不需要返回值
- 查:需要处理返回值
2.1实例
1 |
|
2.2 封装方法修改实例
- (1)新建一个JDBCUtils类,来封装数据库连接,资源关闭操作
1 | /** |
1 | /** |
- (2)重新修改实例
1 |
|
2.3 封装通用的增删改方法
1 | /** |
1 |
|
三、实现查找操作
3.1 概述
- 查找操作对比其他操作,多了个对返回的数据进行接受、处理。
- 对返回的数据,一般会创造一个类来进行接受,属于ORM编程思想,也是“万事万物皆对象”的体现
3.2 实现方法
- (1)查询语句的执行方法是
ResultSet executeQuery()
,会返回一个结果集resultSet方法 - (2)通过
resultSet.next()
方法来判断是否存在一行数据,有就返回true并指针下移,用于条件判断 - (3)通过
resultSet.getXxxx(index)
来获取数据,因为要封装通用方法,一般使用getObject(index)
- 注意:index是从1开始算,并不是0开始
- (4)创建相应的对象,将获取的数据赋值到该对象中,一般使用反射方法
- 注意: 步骤3需要知道一行数据到底有多少列数据;步骤4需要获取到列名,才能利用反射进行数据赋值(注意类的属性名,与查询的列名一致,不一致可以用sql语句别名的方式)
- 解决方法:
- (a)用
resultSet.getMetaData()
的方法来获取数据的原数据 - (b)
resultMetaData.getColumnCount()
来获取列数,解决步骤3 - (c)
resultMetaData.getColumnLabel(index)
,获取列名,index从1开始,解决步骤4
- (a)用
3.3 实例
(1)查询特定表
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
49public static UserTable queryForUserTable(String sql, Object ...args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1.连接数据库
conn = JDBCUtils.getConnection();
//2.预编译sql
ps = conn.prepareStatement(sql);
//3.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1, args[i]);
}
//4.执行并返回结果集
rs = ps.executeQuery();
//5.处理结果集
ResultSetMetaData rsmd = rs.getMetaData();//获取结果集的元数据
int column = rsmd.getColumnCount();//获取列数
//6.处理一行结果集
if (rs.next()){
UserTable u = new UserTable();//创建一个空参对象
for (int i = 0; i < column; i++){
//(1)获取列数据
Object columnValue = rs.getObject(i + 1);
//(2)获取列名
String columnLabel = rsmd.getColumnLabel(i + 1);
//(3)通过反射进行赋值赋值
Class clazz = u.getClass();
Field filed = clazz.getDeclaredField(columnLabel);
filed.setAccessible(true);
filed.set(u, columnValue);
}
return u;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//7.资源关闭
JDBCUtils.close(conn, ps, rs);
}
return null;
}(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
51public static <T> List<T> queryAll(Class<T> clazz, String sql, Object ...args){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1.连接数据库
conn = JDBCUtils.getConnection();
//2.预编译sql
ps = conn.prepareStatement(sql);
//3.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1, args[i]);
}
//4.执行并返回结果集
rs = ps.executeQuery();
//5.处理结果集
ResultSetMetaData rsmd = rs.getMetaData();//获取结果集的元数据
int column = rsmd.getColumnCount();//获取列数
//6.处理多行结果集
ArrayList<T> list = new ArrayList<>();//创建一个List集合
while (rs.next()){
T t = clazz.getDeclaredConstructor().newInstance();//反射创建一个空参对象
for (int i = 0; i < column; i++){
//(1)获取列数据
Object columnValue = rs.getObject(i + 1);
//(2)获取列名
String columnLabel = rsmd.getColumnLabel(i + 1);
//(3)通过反射进行赋值
Field filed = clazz.getDeclaredField(columnLabel);
filed.setAccessible(true);
filed.set(t, columnValue);
}
list.add(t);//添加对象
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
//7.资源关闭
JDBCUtils.close(conn, ps, rs);
}
return null;
}