一次反射的应用

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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class JdbcGetAll {

// 传入表名和类名和Connection对象,会将给定表中的每条数据转换成给定的类的实例.
// 要求,表的字段的字段名和数据类型要和类的字段名和类型一一对应
public List getAll(String tableName, String className, Connection conn) {

// 从给定的类名获得类传至该变量
Class thisClass;

// 类的字段的数组
Field[] thisFields;

// 类的字段的Map,方便根据字段名获取到Field对象
HashMap<String, Field> thisFieldsMap = new HashMap<>();

// 类的构造器
Constructor thisConstructor = null;

// 表的字段名的集合
var COLUMN_NAMEs = new ArrayList<String>();

// 用于盛放生成的对象的数组,最终返回该对象
var thisInstances = new ArrayList();

try {
thisClass = Class.forName(className);
thisConstructor = thisClass.getConstructor();
thisFields = thisClass.getFields();

for (var field : thisFields) {
thisFieldsMap.put(field.getName(), field);
}

} catch (ClassNotFoundException e) {
System.out.println("No class called '" + className + "'");
return null;
} catch (NoSuchMethodException e) {
e.printStackTrace();
}

// 获取到表的字段的sql语句
var sql = "select COLUMN_NAME from information_schema.COLUMNS where table_name = '" + tableName + "'";

PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
var COLUMN_NAME = rs.getString("COLUMN_NAME");
COLUMN_NAMEs.add(COLUMN_NAME);
}
} catch (SQLException e) {
e.printStackTrace();
}

// 获取表的数据
sql = "select * from " + tableName;

try {
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();

// 遍历所有记录,为每条记录生成一个类实例
while (rs.next()) {
try {
// 从类的构造器创建新的实例
var thisInstance = thisConstructor.newInstance();

// 遍历所有表的字段
for (var COLUMN_NAME : COLUMN_NAMEs) {

// 获取到表的字段名对应的对象字段
var field = thisFieldsMap.get(COLUMN_NAME);

// 获取到该条记录该条字段的值
var o = rs.getObject(COLUMN_NAME);

// 为对象的字段设置值
field.set(thisInstance, o);
}
thisInstances.add(thisInstance);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUitl.close(pstmt, conn);
}

return thisInstances;
}

public static void main(String[] args) {
Connection conn = JdbcUitl.getConnection("address", 3306, "dbName", "root", "password");
var jdbcGetAll = new JdbcGetAll();
List res = jdbcGetAll.getAll("teacher", "Teacher", conn);
System.out.println("结果集中共含有" + res.size() + "个元素: {");
for (var re : res) {
System.out.println(" " + re);
}
System.out.println("}");
}
}
JdbcUtil类的代码
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
import java.sql.*;

public class JdbcUitl {
public static Connection getConnection(String address,int port,String dbName,String userName,String passWord){
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://" + address + ":" + port + "/" + dbName,userName,passWord);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}

public static void close(PreparedStatement pstmt,Connection conn){
if(pstmt!=null){
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}