Java如何完成一个通用查询的逻辑需求(JDBC)
1.首先创建一个用于连接以及关闭数据库的类
我们使用配置文件的方式,获取连接数据库的基本条件
创建一个jdbc.properties文件用于存放基本配置信息。如下
// 切记不要加空格
user=用户名
password=密码
url=jdbc:mysql://ip:prot/数据库名字
jdbc=com.mysql.cj.jdbc.Driver
创建连接的方法getConnection,关闭连接的方法CloseConn。具体代码如下:
public class jdbc_conn {
public static Connection getConnection() throws Exception {
Connection connection = null;
// 1. 读取配置文件中的4个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String jdbc = pros.getProperty("jdbc");
// 2.加载驱动
Class.forName(jdbc);
// 3.获取连接
connection = DriverManager.getConnection(url, user, password);
return connection;
}
public static void CloseConn(PreparedStatement preparedStatement, Connection connection, ResultSet resultSet) {
if (preparedStatement != null) {
try {
preparedStatement.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
}catch (SQLException e){
e.printStackTrace();
}
}
System.out.println("关闭成功");
}
}
2. 创建一个Field类,对应数据库某表的字段
这个主要就是对应数据库的某张表的所有字段,具体代码如下:
public class CeshiField {
private int id;
private String name;
private int age;
private String score;
public CeshiField() {
this.id = 0;
this.age = 0;
this.name = null;
this.score = name;
}
public CeshiField(int id, String name, int age, String score) {
this.id = id;
this.name = name;
this.age = age;
this.score = score;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
@Override
public String toString() {
return "CeshiField{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", score='" + score + '\'' +
'}';
}
}
3. 实现如何通用查询某表的数据
- 初始化连接、预编译、结果集
- 连接数据库,预编译sql,通过可变参数,获取预编译填充数据(Object,因为不确定是什么类型)个数
- 获得查询集后,获取其元数据,得到数据库某表的列数以及列名
- 创建属性类对象
- 循环其列数,通过反射的方式,为属性类对象的属性进行赋值
/**
*
* 通用查询操作
* @param sql
* @param args
* @return
*/
public CeshiField queryTYQuery(String sql, Object...args) {
// 初始化
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
// 连接数据库
connection = jdbc_conn.getConnection();
// 预编译sql
preparedStatement = connection.prepareStatement(sql);
for (int i=0; i<args.length; i++) {
// 因为实现不确定是什么类型属性, 用Object
// 对预编译sql 进行赋值
preparedStatement.setObject(i+1, args[i]);
}
// 进行查询操作
resultSet = preparedStatement.executeQuery();
// 获取结果集的元数据
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
// 获取列数(因为是通用查询,获取其列数)
int columnCount = resultSetMetaData.getColumnCount();
if (resultSet.next()) {
// 创建了属性类对象(对应数据库一张表的字段)
CeshiField ceshiField = new CeshiField();
// 处理结果集每列中的数据,利用反射的知识
for (int i = 0; i <columnCount ; i++) {
// 获取列值
Object columnValue = resultSet.getObject(i+1);
// 获取每列的名字
String columnName = resultSetMetaData.getColumnName(i+1);
// 通过反射进行赋值(将columnValue赋值给columnName)
// 数据库的列名对应属性名字, columnName获取的列名==属性名,通过这个名字进行反射赋值
Field field = CeshiField.class.getDeclaredField(columnName);
field.setAccessible(true); //私有属性所以设置
field.set(ceshiField, columnValue); // 进行赋值
}
return ceshiField;
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
测试类 传入对应的预编译sql, 以及对应的值(方法参数为…args可变参数)
@Test
public void test() {
String sql = "select id,name,age from ceshi where id = ?";
CeshiField ceshiField = queryTYQuery(sql, 2);
System.out.println(ceshiField);
}