当前位置: 首页 > news >正文

JDBC工具类封装详解

JDBC工具类封装详解

1. 工具类设计目标

核心目标

  • 代码复用:避免重复的JDBC代码
  • 资源管理:确保连接、语句、结果集的正确关闭
  • 异常处理:统一的异常处理机制
  • 配置管理:集中管理数据库连接参数
  • 事务支持:简化事务操作

2. 基础工具类实现

2.1 配置文件管理

db.properties

# 数据库连接配置
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bank_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456# 连接池配置
jdbc.initialSize=5
jdbc.maxActive=20
jdbc.maxWait=3000

2.2 基础工具类

package com.bank.util;import java.io.InputStream;
import java.sql.*;
import java.util.Properties;/*** JDBC工具类 - 基础版本*/
public class JDBCUtil {private static String driver;private static String url;private static String username;private static String password;// 静态代码块,类加载时初始化配置static {try {// 1. 加载配置文件Properties props = new Properties();InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");props.load(is);// 2. 读取配置driver = props.getProperty("jdbc.driver");url = props.getProperty("jdbc.url");username = props.getProperty("jdbc.username");password = props.getProperty("jdbc.password");// 3. 注册驱动Class.forName(driver);} catch (Exception e) {throw new RuntimeException("JDBC工具类初始化失败", e);}}/*** 获取数据库连接*/public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url, username, password);}/*** 关闭连接*/public static void close(Connection conn) {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}/*** 关闭语句*/public static void close(Statement stmt) {if (stmt != null) {try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}}/*** 关闭结果集*/public static void close(ResultSet rs) {if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}}/*** 关闭所有资源*/public static void close(Connection conn, Statement stmt, ResultSet rs) {close(rs);close(stmt);close(conn);}/*** 关闭连接和语句*/public static void close(Connection conn, Statement stmt) {close(stmt);close(conn);}
}

3. 增强版工具类(推荐)

3.1 支持连接池的工具类

package com.bank.util;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;/*** JDBC工具类 - 增强版(支持连接池)*/
public class JDBCUtil {private static DataSource dataSource;private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();static {try {// 1. 加载配置文件Properties props = new Properties();InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");props.load(is);// 2. 创建连接池dataSource = DruidDataSourceFactory.createDataSource(props);} catch (Exception e) {throw new RuntimeException("数据库连接池初始化失败", e);}}/*** 获取数据库连接(从连接池)*/public static Connection getConnection() throws SQLException {// 首先从ThreadLocal中获取,支持事务Connection conn = threadLocal.get();if (conn != null) {return conn;}return dataSource.getConnection();}/*** 获取数据源*/public static DataSource getDataSource() {return dataSource;}/*** 开启事务*/public static void beginTransaction() throws SQLException {Connection conn = threadLocal.get();if (conn != null) {throw new SQLException("已经开启事务,不能重复开启");}conn = getConnection();conn.setAutoCommit(false);threadLocal.set(conn);}/*** 提交事务*/public static void commitTransaction() throws SQLException {Connection conn = threadLocal.get();if (conn == null) {throw new SQLException("没有开启事务,不能提交");}try {conn.commit();} finally {conn.setAutoCommit(true);close(conn);threadLocal.remove();}}/*** 回滚事务*/public static void rollbackTransaction() throws SQLException {Connection conn = threadLocal.get();if (conn == null) {throw new SQLException("没有开启事务,不能回滚");}try {conn.rollback();} finally {conn.setAutoCommit(true);close(conn);threadLocal.remove();}}/*** 关闭连接(特殊处理事务连接)*/public static void close(Connection conn) {// 如果是事务连接,不真正关闭,由事务方法管理if (threadLocal.get() != null) {return;}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}// 其他close方法保持不变...
}

4. 数据库操作模板类

4.1 查询模板

/*** 数据库操作模板类*/
public class JDBCTemplate {/*** 执行查询(带结果集处理)*/public static <T> T executeQuery(String sql, ResultSetHandler<T> handler, Object... params) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JDBCUtil.getConnection();ps = conn.prepareStatement(sql);// 设置参数setParameters(ps, params);rs = ps.executeQuery();return handler.handle(rs);} catch (SQLException e) {throw new RuntimeException("数据库查询失败", e);} finally {JDBCUtil.close(conn, ps, rs);}}/*** 执行更新(INSERT/UPDATE/DELETE)*/public static int executeUpdate(String sql, Object... params) {Connection conn = null;PreparedStatement ps = null;try {conn = JDBCUtil.getConnection();ps = conn.prepareStatement(sql);// 设置参数setParameters(ps, params);return ps.executeUpdate();} catch (SQLException e) {throw new RuntimeException("数据库更新失败", e);} finally {JDBCUtil.close(conn, ps);}}/*** 批量更新*/public static int[] executeBatch(String sql, List<Object[]> paramsList) {Connection conn = null;PreparedStatement ps = null;try {conn = JDBCUtil.getConnection();ps = conn.prepareStatement(sql);for (Object[] params : paramsList) {setParameters(ps, params);ps.addBatch();}return ps.executeBatch();} catch (SQLException e) {throw new RuntimeException("批量更新失败", e);} finally {JDBCUtil.close(conn, ps);}}/*** 设置预处理参数*/private static void setParameters(PreparedStatement ps, Object... params) throws SQLException {if (params != null) {for (int i = 0; i < params.length; i++) {ps.setObject(i + 1, params[i]);}}}/*** 结果集处理器接口*/public interface ResultSetHandler<T> {T handle(ResultSet rs) throws SQLException;}
}

4.2 常用结果集处理器

/*** 常用的结果集处理器实现*/
public class ResultSetHandlers {/*** 返回单个对象*/public static final ResultSetHandler<Object> SINGLE_OBJECT = rs -> {if (rs.next()) {return rs.getObject(1);}return null;};/*** 返回单个Long值(用于count等)*/public static final ResultSetHandler<Long> SINGLE_LONG = rs -> {if (rs.next()) {return rs.getLong(1);}return 0L;};/*** 返回Map结果*/public static final ResultSetHandler<Map<String, Object>> SINGLE_MAP = rs -> {if (rs.next()) {ResultSetMetaData metaData = rs.getMetaData();int columnCount = metaData.getColumnCount();Map<String, Object> map = new HashMap<>();for (int i = 1; i <= columnCount; i++) {String columnName = metaData.getColumnLabel(i);Object value = rs.getObject(i);map.put(columnName, value);}return map;}return null;};/*** 返回Bean对象*/public static <T> ResultSetHandler<T> beanHandler(Class<T> beanClass) {return rs -> {if (rs.next()) {return mapRowToBean(rs, beanClass);}return null;};}/*** 返回Bean列表*/public static <T> ResultSetHandler<List<T>> beanListHandler(Class<T> beanClass) {return rs -> {List<T> list = new ArrayList<>();while (rs.next()) {list.add(mapRowToBean(rs, beanClass));}return list;};}/*** 将结果集行映射到Bean*/private static <T> T mapRowToBean(ResultSet rs, Class<T> beanClass) throws SQLException {try {T bean = beanClass.newInstance();ResultSetMetaData metaData = rs.getMetaData();int columnCount = metaData.getColumnCount();for (int i = 1; i <= columnCount; i++) {String columnName = metaData.getColumnLabel(i);Object value = rs.getObject(i);// 使用反射设置属性值setBeanProperty(bean, columnName, value);}return bean;} catch (Exception e) {throw new RuntimeException("映射Bean失败", e);}}/*** 反射设置Bean属性*/private static void setBeanProperty(Object bean, String columnName, Object value) throws Exception {// 简单的属性设置逻辑// 实际应用中可以使用BeanUtils等工具类String setterName = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);java.lang.reflect.Method method = findSetterMethod(bean.getClass(), setterName, value);if (method != null) {method.invoke(bean, value);}}private static java.lang.reflect.Method findSetterMethod(Class<?> clazz, String setterName, Object value) {for (java.lang.reflect.Method method : clazz.getMethods()) {if (method.getName().equals(setterName) && method.getParameterCount() == 1) {// 简单的类型匹配Class<?> paramType = method.getParameterTypes()[0];if (value == null || paramType.isInstance(value) || isCompatibleType(paramType, value.getClass())) {return method;}}}return null;}private static boolean isCompatibleType(Class<?> paramType, Class<?> valueType) {// 简单的类型兼容性检查if (paramType == int.class && valueType == Integer.class) return true;if (paramType == long.class && valueType == Long.class) return true;if (paramType == double.class && valueType == Double.class) return true;if (paramType == boolean.class && valueType == Boolean.class) return true;return false;}
}

5. 使用示例

5.1 基础使用

public class AccountDAO {/*** 查询账户余额*/public double getBalance(String actno) {String sql = "SELECT balance FROM act WHERE actno = ?";return JDBCTemplate.executeQuery(sql, rs -> {if (rs.next()) {return rs.getDouble("balance");}throw new RuntimeException("账户不存在: " + actno);}, actno);}/*** 更新账户余额*/public int updateBalance(String actno, double newBalance) {String sql = "UPDATE act SET balance = ? WHERE actno = ?";return JDBCTemplate.executeUpdate(sql, newBalance, actno);}/*** 转账操作(带事务)*/public boolean transfer(String fromActno, String toActno, double money) {try {// 开启事务JDBCUtil.beginTransaction();// 扣款String debitSQL = "UPDATE act SET balance = balance - ? WHERE actno = ?";int count1 = JDBCTemplate.executeUpdate(debitSQL, money, fromActno);if (count1 == 0) {throw new RuntimeException("扣款失败,账户不存在: " + fromActno);}// 存款String creditSQL = "UPDATE act SET balance = balance + ? WHERE actno = ?";int count2 = JDBCTemplate.executeUpdate(creditSQL, money, toActno);if (count2 == 0) {throw new RuntimeException("存款失败,账户不存在: " + toActno);}// 提交事务JDBCUtil.commitTransaction();return true;} catch (Exception e) {// 回滚事务try {JDBCUtil.rollbackTransaction();} catch (SQLException ex) {ex.printStackTrace();}throw new RuntimeException("转账失败: " + e.getMessage(), e);}}
}

5.2 使用Bean映射

public class AccountDAO {/*** 查询账户信息(返回Bean)*/public Account getAccount(String actno) {String sql = "SELECT actno, balance, create_time FROM act WHERE actno = ?";return JDBCTemplate.executeQuery(sql, ResultSetHandlers.beanHandler(Account.class), actno);}/*** 查询所有账户*/public List<Account> getAllAccounts() {String sql = "SELECT actno, balance, create_time FROM act";return JDBCTemplate.executeQuery(sql, ResultSetHandlers.beanListHandler(Account.class));}
}/*** 账户实体类*/
public class Account {private String actno;private double balance;private Date createTime;// getter和setter方法public String getActno() { return actno; }public void setActno(String actno) { this.actno = actno; }public double getBalance() { return balance; }public void setBalance(double balance) { this.balance = balance; }public Date getCreateTime() { return createTime; }public void setCreateTime(Date createTime) { this.createTime = createTime; }
}

6. Maven依赖

6.1 基础依赖

<dependencies><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!-- Druid连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.18</version></dependency><!-- 日志 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.9</version></dependency>
</dependencies>

7. 最佳实践

7.1 配置管理

  • 使用配置文件管理数据库连接参数
  • 区分开发、测试、生产环境配置
  • 敏感信息加密存储

7.2 异常处理

  • 统一异常处理,避免SQLException污染业务代码
  • 提供有意义的异常信息
  • 记录详细的错误日志

7.3 性能优化

  • 使用连接池管理数据库连接
  • 合理设置连接池参数
  • 及时关闭数据库资源

7.4 事务管理

  • 在Service层管理事务,而不是DAO层
  • 使用声明式事务(如Spring @Transactional)
  • 正确处理事务的传播行为

这种JDBC工具类封装可以大大简化数据库操作代码,提高开发效率,同时保证代码的质量和性能。

http://www.dtcms.com/a/432742.html

相关文章:

  • 北湖区网站建设公司哪家好2019年做网站还有机会吗
  • 酒业网站建设html静态页面
  • 建站是什么东西网站开发数据库
  • 再谈线程同步——读写锁与屏障
  • 做外贸网站如何宁波h5模板建站
  • 网站建设费入如保入账wordpress 导航栏 搜索
  • 温岭高端网站设计哪家好自己的网站怎么和百度做友链
  • 用excel 做网站长沙门户网站建设公司
  • 传媒网站给行业做宣传wordpress博客数据库
  • 滨州网站网站建设wordpress伪静态设置
  • 公司要做网站wordpress获取父分类
  • 怎样给网站做app做期货看啥子网站
  • 重庆建设管理信息网站别人帮做的网站怎么修改
  • 自建站价格html5做手机网站建设
  • 电销做网站的话术h5页面怎么制作免费
  • 移动网站是什么意思哪些网站可以发广告
  • 资兴网站设计住房和城乡建设厅官网证件查询
  • 盐城市城乡和住房建设厅网站cn域名续费多少钱一年
  • 视频类网站模板个人小白用织梦好还是wordpress好
  • seo网站关键词优化建网站公司哪个比较好
  • 网站开发项目源码360开户
  • 昭通市网站建设广州做网站哪家专业
  • 苏州沧浪做网站哪家好wordpress 有没有上级目录的写权限
  • 中国有没有一家做茶叶的网站浏览器打开网站
  • 怎么申请免费企业网站建设工程扣分查询网站
  • 小江网站建设各大网站投放广告怎么做
  • 内衣网站建设推广无刷新网站
  • 网站建设银行业务预约纪念币猪年纪念币预约人流医院网站建设
  • 教育培训学校网站建设方案wordpress怎么设置静态主页
  • 怎么做网站点击率监控工具docker 搭建 wordpress