JDBC帮助类的封装
通过前面的学习可以发现,JDBC操作重复代码非常多,完全可以把它封装起来。
完整代码
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcUtil {
private Connection conn = null;
private PreparedStatement stmt = null;
private ResultSet rs = null;
private static String driver = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://localhost:3306/Student";
private String user = "root";
private String password = "root";
/**
* 加载驱动(静态代码块,类加载时执行一次)
*/
static {
}
/**
* 获取数据库连接
*/
public Connection getCon() {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
conn = (Connection) DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 增删改通用方法
* @param sql
* @param obj
*/
public int update(String sql, Object... obj) {
int count = 0;
conn = getCon();
try {
stmt = conn.prepareStatement(sql);
if (obj != null) {
for (int i = 0; i < obj.length; i++) {
stmt.setObject(i + 1, obj[i]);
}
}
count = stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
close();
}
return count;
}
/**
* 查询通用方法
* @param sql
* @param obj
*/
public ResultSet Query(String sql, Object... obj) {
conn = getCon();
try {
stmt = conn.prepareStatement(sql);
if (obj != null) {
for (int i = 0; i < obj.length; i++) {
stmt.setObject(i + 1, obj[i]);
}
}
rs = stmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
// 注意:查询后不能在这里关闭连接,否则ResultSet就拿不到数据了
return rs;
}
/**
* 关闭资源
*/
public void close() {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}Code language: JavaScript (javascript)
补充说明
- 驱动类名写的是
com.mysql.jdbc.Driver,这是 mysql-connector-java 5.x 的写法。如果用的是 8.x 版本,需要改成com.mysql.cj.jdbc.Driver - 静态代码块里原本应该写
Class.forName(driver),这里留空了,实际应该补上:
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}Code language: JavaScript (javascript)
然后把 getCon() 里的 Class.forName(driver) 删掉,驱动只需加载一次
update()方法用可变参数Object... obj接收 ? 的值,内部循环调用setObject()设置参数,适用于 insert、update、delete 和 DDLQuery()方法返回 ResultSet,调用方拿到结果集遍历完之后需要手动调用close()关闭资源,不能在 Query() 内部关闭- 每次调用
getCon()都会新建一个连接,频繁创建连接开销大。实际项目中应该用数据库连接池(如 Druid、HikariCP、DBCP)替代 - 这个工具类适合学习阶段使用,生产环境建议用 MyBatis、JPA 等成熟框架,或者至少加上连接池和事务管理
Previous: 使用JDBC查找表记录