由于每次写JDBC连接数据库时都非常麻烦所以我们来编写一个JDBC的工具类。
我们先了解一下普通的JDBC有什么步骤:
1,加载驱动
Class.forName("com.mysql.jdbc.Driver");
2,获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_test","root","root");
3,预处理SQL语句
String sql = "select * from user where username = ? and password = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
4,设置参数
preparedStatement.setString(1,"XXXX");
preparedStatement.setString(2,"XXXX");
5,执行SQL语句,并获取结果集
ResultSet resultSet = preparedStatement.executeQuery();
6,解析结果集(查询独有)
if (resultSet.next()){
msg.setText("登录成功");
}else{
msg.setText("登录失败");
}
7,关闭连接
connection.close();
首先我们看一下有什么步骤是不会变的。
第一步的加载驱动我们只需要触发了这一串代码就可以了,所以我们可以将它写在工具类的静态代码块中在工具类被创建是就加载。
//静态加载
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
第二步,我们在项目中很大的几率并不会使用到两个库(遇到再说),所以也是可以封装成为一个方法。
/**
* 获取连接
*
* @return
* @throws SQLException
*/
public static Connection getConn() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_test", "root", "root");
}
第三步预处理SQL语句和参数处理,我们也是可以封装的,一定要使用预处理,要不会被SQL注入的。
/**
* 预处理sql语句
*
* @param conn 连接
* @param sql SQL语句
* @param params 参数列表
* @return
* @throws SQLException
*/
public static PreparedStatement getPre(Connection conn, String sql, Object... params) throws SQLException {
PreparedStatement pre = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pre.setObject(i+1, params[i]);
}
return pre;
}
第四步执行SQL语句并返回结果,在这里就有了分支,
executeUpdate方法负责增删改,并返回受影响行数
executeQuery方法负责查,并返回结果集
先写增删改的工具方法:
/**
* 执行executeUpdate
* @param pre
* @return
* @throws SQLException
*/
public static int executeUpdate(PreparedStatement pre) throws SQLException {
return pre.executeUpdate();
}
在写查的工具方法:
/**
* 执行executeQuery
* @param pre
* @return
* @throws SQLException
*/
public static ResultSet executeQuery(PreparedStatement pre) throws SQLException {
return pre.executeQuery();
}
最后在写一个解析结果集的方法,将结果集放入在实体类集合中
/**
* 将数据库中的结果集转换为集合
*
* @param clazz 实体类的反射
* @param <T>
* @return
* @throws SQLException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
*/
public static <T> T getBean(PreparedStatement pre, List<T> list, Class<T> clazz) throws SQLException, IllegalAccessException, InstantiationException, InvocationTargetException {
//执行SQL语句返回结果集
ResultSet resultSet = DBUtils.executeQuery(pre);
//获取数据库原数据信息
ResultSetMetaData metaData = resultSet.getMetaData();
//创建一个对象
T t = null;
//获取下一行结果
while (resultSet.next()) {
//反射创建实例
t = clazz.newInstance();
//循环获取结果并通过反射到实体类中
for (int i = 0; i < metaData.getColumnCount(); i++) {
//获取列名
String catalogName = metaData.getColumnName(i + 1);
//获取clazz中的所有方法如果匹配则反射调用该方法
Method[] Methods = clazz.getDeclaredMethods();
for (Method method : Methods) {
//所有方法名比较set+字段名如果有对应的方法则通过反射调用该方法将值传入
if (method.getName().equalsIgnoreCase("set" + catalogName)) {
//获取对应的值
Object o = resultSet.getObject(catalogName);
//TODO 将数据库类型转化为相应的java类型
//反射掉用该列对应的set方法赋值
SqlTypeTOJType(method, t, o, catalogName);
}
}
}
//将该对象添加入传入的集合中
list.add(t);
}
return t;
}
/**
* 将数据库类型转为java类型
*
* @param method 方法
* @param t 实体类泛型
* @param o 数据库数据
* @param columnTypeName 列名
* @param <T>
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
private static <T> void SqlTypeTOJType(Method method, T t, Object o, String columnTypeName) throws InvocationTargetException, IllegalAccessException {
if (columnTypeName.equalsIgnoreCase("INT")) {
method.invoke(t, Integer.parseInt(o.toString()));
} else if (columnTypeName.equalsIgnoreCase("DATE")) {
method.invoke(t, LocalDate.parse(o.toString()));
} else if (columnTypeName.equalsIgnoreCase("DATETIME")) {
Timestamp timestamp = Timestamp.valueOf(o.toString());
method.invoke(t, timestamp.toLocalDateTime());
} else {
method.invoke(t, o.toString());
}
}
来使用一下则个功能
创建实体类:
public class t_student {
private int id;
private String name;
private int class_id;
public int getid() {
return id;
}
public void setid(String id) {
this.id = Integer.parseInt(id);
}
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public int getclass_id() {
return class_id;
}
public void setclass_id(String class_id) {
this.class_id = Integer.parseInt(class_id);;
}
@Override
public String toString() {
return "t_student{" +
"id=" + id +
", name='" + name + '\'' +
", class_id=" + class_id +
'}';
}
}
创建一个main方法来测试
//创建一个实体类的集合
ArrayList<t_student> list = new ArrayList<>();
//工具类获取连接和处理SQL语句
PreparedStatement pre = DBUtils.getPre(DBUtils.getConn(), "select * from t_student");
//使用工具类的解析结果集的方法
DBUtils.getBean(pre, list, t_student.class);
//遍历结果集集合
Iterator<t_student> iterator = list.iterator();
while (iterator.hasNext()) {
t_student ts = iterator.next();
System.out.println(ts.getid() + "\t" + ts.getname() + "\t" + ts.getclass_id());
}
得出结果
数据对比
这样我们的JDBC工具类就完成了。