引入
用原生的JDBC操作数据库时,我们会发现有许多重复的操作,例如加载驱动,获取连接对象,关闭连接等操作,在查询数据后对对象一个个赋值也非常麻烦,我们可以封装一个JDBC工具类用于处理常见的数据库操作,再利用反射机制封装增删改查操作。
实现效果
直接通过工具类进行增删改查,并返回相关对象。
我们利用反射机制实现
实现思路
- 1.通过Properties对象读取配置文件加载数据库连接参数,加载驱动。
- 2.封装两个基础方法,一个用于获取数据库连接,一个用于关闭连接。
- 3.封装查询方法,参数一:sql语句,参数二:字节码对象,因为我们需要得到相应的对象,所以我们需要使用泛型,并传入字节码对象,参数三:可变参数,这里为了防止sql注入,使用的是PreparedStatement对象,进行sql预编译,所以就需要传入可变参数,因为占位符的个数是未知的。
- 4.封装更新方法(因为删除和修改都是返回影响条数所以可以共用一个方法),参数一:sql语句,参数二:可变参数,原因同上。
配置文件
在src目录下创建配置文件jdbc.properties,里面放置数据库连接所需要的的相关参数。
注意:记得修改账号密码和url,这里用的数据库时mysql5.4,mysql8的driver要修改为com.mysql.cj.jdbc.Driver
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/lzp
user=root
password=123456
JDBC工具类
package day29JDBC01;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* JDBC工具类
*
* @author lzp
* @Date 2020年8月10日 上午11:49:07
*/
public final class JDBCUtils {
private static Properties p = new Properties();
//静态代码块在类被加载时就会加载
static {
// 加载配置文件
try {
p.load(new FileInputStream(new File("src/jdbc.properties")));
// 加载驱动
Class.forName(p.getProperty("driver"));
} catch (Exception e) {
e.printStackTrace();
}
}
//禁止new 对象
private JDBCUtils(){
}
public static Connection getConnection() throws Exception {
Connection conn = null;
conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("user"), p.getProperty("password"));
return conn;
}
// 查找一个数据
public static <T> T query(String sql, Class<T> clazz, String... args) {
T obj = null;
Connection connection = null;
PreparedStatement pst = null;
ResultSet result = null;
try {
Constructor<T> cons = clazz.getConstructor();
obj = cons.newInstance();
// 查询数据库
connection = getConnection();
pst = connection.prepareStatement(sql);
// 设置占位符
if (args.length != 0) {
for (int i = 1; i <= args.length; i++) {
pst.setObject(i, args[i - 1]);
}
}
result = pst.executeQuery();
if(result.next()){
//查询到值则给属性赋值
// 获取所有本类属性的名称
Field[] names = clazz.getDeclaredFields();
for (Field field : names) {
field.setAccessible(true);
field.set(obj, result.getObject(field.getName()));
}
}else{
//没查询到值则返回null
obj = null;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close(connection,pst,result);
}
return obj;
}
// 查找多个数据
public static <T> List<T> queryList(String sql, Class<T> clazz, String... args) {
List<T> list = new ArrayList<>();
T obj = null;
Connection connection = null;
PreparedStatement pst = null;
ResultSet result = null;
try {
Constructor<T> cons = clazz.getConstructor();
// 查询数据库
connection = getConnection();
pst = connection.prepareStatement(sql);
// 设置占位符
if (args.length != 0) {
for (int i = 1; i <= args.length; i++) {
pst.setObject(i, args[i - 1]);
}
}
result = pst.executeQuery();
// 讲查询出的元素装进集合之中
// 获取所有本类属性的名称
Field[] names = clazz.getDeclaredFields();
while (result.next()) {
obj = cons.newInstance();
for (Field field : names) {
field.setAccessible(true);
field.set(obj, result.getObject(field.getName()));
}
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close(connection,pst,result);
}
return list;
}
//执行更新和删除等操作
public static int update(String sql,String... args){
int res = 0;
Connection connection = null;
PreparedStatement pst = null;
try {
connection = getConnection();
pst = connection.prepareStatement(sql);
// 设置占位符
if (args.length != 0) {
for (int i = 1; i <= args.length; i++) {
pst.setObject(i, args[i - 1]);
}
}
res = pst.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
close(connection,pst,null);
}
return res;
}
//关闭连接
public static void close(Connection conn,Statement pst,ResultSet res){
try {
if (res != null) {
res.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pst != null) {
pst.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
测试
javaBean对象
这里测试使用的对象对应job表
对应对象代码:
/**
* 工作类
* @author lzp
* @Date 2020年8月10日 上午11:45:43
*/
public class Job {
private int id;
private String title;
private double salary;
public Job() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Job [id=" + id + ", title=" + title + ", salary=" + salary + "]";
}
}
测试类
测试类如下:
import java.util.List;
/**
* @author lzp
* @Date 2020年8月10日 下午4:09:42
*/
public class Test {
public static void main(String[] args) {
int res1 = JDBCUtils.update("insert into job values(null,'教师',7888),(null,'包工头',199999)");
Job job = JDBCUtils.query("select * from job where id = ?", Job.class, "1");
List<Job> jobs = JDBCUtils.queryList("select * from job", Job.class);
int res2 = JDBCUtils.update("delete from job where id = ?", "1");
System.out.println(res1);
System.out.println(job);
System.out.println(jobs);
System.out.println(res2);
}
}
测试结果如下:
执行后的数据库: