JDBC学习3--DAO设计模式

DAO: Data Access Object

示例地址:https://github.com/lizhongzhen11/jdbcStudy-1

why?

实现功能的模块化。更有利于代码的维护和升级。
DAO 可以被子类继承或直接使用

what?

访问数据信息的类。包含了对数据的 CRUD(create, read, update, delete)。而不包含任何业务相关的信息。

how?

使用JDBC编写 DAO 可能会包含的方法:

1
2
3
4
5
6
7
8
9
10
// insert, update, delete 操作都可以包含在里面
void update(String sql, Object ... args)
- - -
// slelect
// 查询一条记录,返回对应的对象
<T> T get(Class<T> clazz, String sql, Object ... args)
// 查询多条记录,返回对应的对象的集合
<T> List<T> getForList(Class<T> clazz, String sql, Object ... args)
// 返回某条记录的某一个字段的值或一个统计的值(一共有多少条记录等.)
<E> E getForValue(String sql, Object ... args)

完善:

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
public class Dao {
// insert, update, delete 操作都可以包含在里面
public void update(String sql, Object ... args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try{
connection = JDBCTest.getConnection2();
preparedStatement = connection.prepareStatement(sql);
for(int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTest.release(null, preparedStatement, connection);
}
}
// slelect
// 查询一条记录,返回对应的对象
public <T> T get(Class<T> clazz, String sql, Object ... args) {
T entity = null;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try{
//1. 获取Connection
connection = JDBCTest.getConnection2();
//2. 获取PreparedStatement
preparedStatement = connection.prepareStatement(sql);
//3. 填充占位符
for(int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
//4. 进行查询,得到ResultSet
resultSet = preparedStatement.executeQuery();
//5. 若ResultSet中有记录,准备一个Map<String, Object>: 键: 存放的别名, 值: 存放列的值
if(resultSet.next()) {
Map<String, Object> values = new HashMap<String, Object>();
//6. 得到 ResultSetMetaData 对象
ResultSetMetaData data = (ResultSetMetaData) resultSet.getMetaData();
//7. 处理 ResultSet,把指针乡下移动一个单位
//8. 由 ResultSetMetaData 对象得到结果集中有多少列
int columnCount = data.getColumnCount();
//9. 由 ResultSetMetaData 得到每一列的别名,由 ResultSet 得到具体每一列的值
for(int i = 0; i < columnCount; i++) {
String columnLabel = data.getColumnLabel(i + 1);
Object columnValue = resultSet.getObject(i + 1);
//10. 填充Map对象
values.put(columnLabel, columnValue);
}
//11. 用反射创建 Class 对应的对象
entity = clazz.newInstance();
//12. 遍历 Map 对象,用反射填充对象的属性值:属性名为 Map 中的 key,属性值为 Map 中的 value
for(Map.Entry<String, Object> entry: values.entrySet()) {
String propertyName = entry.getKey();
Object value = entry.getValue();
ReflectionUtils.setFieldValue(entity, propertyName, value);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTest.release(resultSet, preparedStatement, connection);
}
return entity;
}
// 查询多条记录,返回对应的对象的集合
public <T> List<T> getForList(Class<T> clazz, String sql, Object ... args) {
return null;
}
// 返回某条记录的某一个字段的值或一个统计的值(一共有多少条记录等.)
public <E> E getForValue(String sql, Object ... args) {
return null;
}
}

DataBaseMetaData(了解)

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
public class MetaData {
/*
* DataBaseMetaData 是描述数据库的元数据对象
* 可以由 Connection 得到
* 了解
*/
@Test
public void testDataBaseMetaData() {
DatabaseMetaData databaseMetaData = null;
Connection connection = null;
ResultSet resultSet = null;
try{
connection = JDBCTest.getConnection2();
databaseMetaData = connection.getMetaData();
// 可以得到数据库本身的一些基本信息
// 得到数据库的版本号
int version = databaseMetaData.getDatabaseMajorVersion();
System.out.println(version);
// 得到连接到数据库的用户名
String user = databaseMetaData.getUserName();
System.out.println(user);
// 得到 Mysql 中有哪些数据库
resultSet = databaseMetaData.getCatalogs();
while(resultSet.next()){
System.out.println(resultSet.getString(1));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTest.release(resultSet, null, connection);
}
}
/*
* ResultSetMetaData: 描述结果集的元数据
* 可以得到结果集中的基本信息: 结果集中有哪些列,列名,列的别名等
* 结合反射可以写出通用的查询
*/
@Test
public void testResultSetMetaData() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String sql = "select * from jdbcstudenttest";
try{
connection = JDBCTest.getConnection2();
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
//1. 得到 ResultSetMetaData 对象
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
//2. 得到列的个数
int columnCount = resultSetMetaData.getColumnCount();
System.out.println(columnCount);
for(int i = 0; i < columnCount; i++) {
//3. 得到列名
String columnName = resultSetMetaData.getColumnName(i + 1);
//4. 得到列的别名
String columnLabel = resultSetMetaData.getColumnLabel(i + 1);
System.out.println(columnName + ":" + columnLabel);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTest.release(resultSet, preparedStatement, connection);
}
}
}
Newer Post

JDBC学习4--数据库事务

示例地址:https://github.com/lizhongzhen11/jdbcStudy-1 数据库事务 在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。 为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持, …

继续阅读
Older Post

JDBC学习2

示例地址:https://github.com/lizhongzhen11/jdbcStudy-1 SQL 注入攻击SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,从而利用系统的 SQL 引擎完成恶意行为的做法 对于 Java …

继续阅读