
JDBC DAO及其实现类
发布日期:2021-05-07 08:57:30
浏览次数:20
分类:精选文章
本文共 13129 字,大约阅读时间需要 43 分钟。
Java数据库访问优化:基于DAO模式的泛型处理方案
DAO模式设计与实现
在数据库开发中,Data Access Object(DAO)模式通过将数据访问逻辑封装为独立的类,实现了对数据库操作的统一管理。以下是基于Java泛型的DAO实现方案:
1. 基础DAO类设计
package indi.zhihuali2.DAO;import indi.zhihuali.util.JDBCUtils;import java.lang.reflect.Field;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;/** * @author zhihua.li * @date 2020/7/28 - 21:33 * DAO:Data Access Object访问数据信息的类和接口,包括了对数据的CRUD(Create、Retrieval、Update、Delete),而不包含任何业务相关的信息。 * 有时也称作:BaseDAO * 作用:为了实现功能的模块化,更有利于代码的维护和升级。 */public abstract class BaseDAO{ private static final String TAG = "BaseDAO"; private Class clazz; { // 获取当前BaseDAO的子类继承的父类中的泛型类型 // 这里的this子类在实例化对象时会先把父类对象实例化 // 因此在这里初始化父类泛型是非常合适的 Type genericSuperclass = this.getClass().getGenericSuperclass(); ParameterizedType pty = (ParameterizedType) genericSuperclass; // 获取父类的泛型参数(可能多个,但获取父类泛型类型就是第一个) Type[] actualTypeArguments = pty.getActualTypeArguments(); // 泽然型的第一个参数 clazz = (Class ) actualTypeArguments[0]; } // 增删改操作 public int update(Connection connection, String sql, Object... args) { try { if (connection == null) { throw new SQLException("数据库连接为空"); } if (sql == null) { throw new SQLException("查询SQL语句为空"); } if (args == null || args.length == 0) { throw new SQLException("参数为空"); } PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i + 1, args[i]); } return preparedStatement.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } finally { try { connection.setAutoCommit(true); } catch (SQLException throwables) { throwables.printStackTrace(); } JDBCUtils.closeResource(connection, preparedStatement, null); } } catch (SQLException e) { e.printStackTrace(); } return 0; } // 查询返回集合的方法 public ArrayList getList(Connection connection, String sql, Object... args) { try { if (connection == null) { throw new SQLException("数据库连接为空"); } if (sql == null) { throw new SQLException("查询SQL语句为空"); } if (args == null || args.length == 0) { throw new SQLException("参数为空"); } PreparedStatement preparedStatement = null; ResultSet resultSet = null; ArrayList ts = new ArrayList<>(); try { preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i + 1, args[i]); } resultSet = preparedStatement.executeQuery(); if (resultSet == null) { return ts; } ResultSetMetaData rsmd = resultSet.getMetaData(); int columnCount = rsmd.getColumnCount(); while (resultSet.next()) { T t = clazz.getDeclaredConstructor().newInstance(); for (int i = 0; i < columnCount; i++) { Object columnValue = resultSet.getObject(i + 1); String columnName = rsmd.getColumnLabel(i + 1); Field field = clazz.getDeclaredField(columnName); field.setAccessible(true); field.set(t, columnValue); } ts.add(t); } } catch (SQLException e) { throw new RuntimeException(e); } finally { JDBCUtils.closeResource(connection, preparedStatement, resultSet); } return ts; } catch (SQLException e) { e.printStackTrace(); } return null; } // 查询返回单个对象的方法 public T getInstance(Connection connection, String sql, Object... args) { try { if (connection == null) { throw new SQLException("数据库连接为空"); } if (sql == null) { throw new SQLException("查询SQL语句为空"); } if (args == null || args.length == 0) { throw new SQLException("参数为空"); } PreparedStatement preparedStatement = null; ResultSet resultSet = null; T t = null; try { preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i + 1, args[i]); } resultSet = preparedStatement.executeQuery(); if (resultSet == null) { return null; } ResultSetMetaData metaData = resultSet.getMetaData(); int columnCount = metaData.getColumnCount(); if (resultSet.next()) { t = clazz.getDeclaredConstructor().newInstance(); for (int i = 0; i < columnCount; i++) { Object objectValue = resultSet.getObject(i + 1); String columnName = metaData.getColumnLabel(i + 1); Field declaredField = clazz.getDeclaredField(columnName); declaredField.setAccessible(true); declaredField.set(t, objectValue); } } } catch (SQLException e) { throw new RuntimeException(e); } finally { try { connection.setAutoCommit(true); } catch (SQLException throwables) { throwables.printStackTrace(); } JDBCUtils.closeResource(connection, preparedStatement, resultSet); } return t; } catch (SQLException e) { e.printStackTrace(); } return null; } // 用于查询特殊值的通用方法 public E getValue(Connection connection, String sql, Object... args) { try { if (connection == null) { throw new SQLException("数据库连接为空"); } if (sql == null) { throw new SQLException("查询SQL语句为空"); } if (args == null || args.length == 0) { throw new SQLException("参数为空"); } PreparedStatement preparedStatement = null; ResultSet resultSet = null; E e = null; try { preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i + 1, args[i]); } resultSet = preparedStatement.executeQuery(); if (resultSet == null) { return null; } while (resultSet.next()) { e = (E) resultSet.getObject(1); } } catch (SQLException e) { throw new RuntimeException(e); } finally { try { connection.setAutoCommit(true); } catch (SQLException throwables) { throwables.printStackTrace(); } JDBCUtils.closeResource(connection, preparedStatement, resultSet); } return e; } catch (SQLException e) { e.printStackTrace(); } return null; }}
2. 接口设计
package indi.zhihuali2.DAO;import indi.zhihuali2.bean.Book;import java.sql.Connection;import java.sql.Date;import java.util.List;/** * @author zhihua.li * @date 2020/7/28 - 21:48 * DAO(Data Access Object)数据访问对象 * 用于规范对于book表的常用操作 */public interface BookDAO { // 将book对象添加到数据库中 void insert(Connection connection, Book book); // 根据指定id删除表中相应记录 void deleteById(Connection connection, int id); // 根据内存中的book对象 修改数据表中指定记录 void updateById(Connection connection, Book book); // 根据指定id查询得到对应的Book对象 Book getBookById(Connection connection, int id); // 查询表中全部记录构成的Book对象集合 ListgetAllBooksById(Connection connection); // 返回数据表中记录个数 Long getCount(Connection connection); // 返回数据表中出生日期最大的对象 Date getMaxBirth(Connection connection);}
3. 实现类设计
package indi.zhihuali2.DAO;import indi.zhihuali.util.JDBCUtils;import indi.zhihuali2.bean.Book;import org.junit.Test;import java.sql.Connection;import java.sql.Date;import java.util.List;import static org.junit.Assert.*;/** * @author zhihua.li * @date 2020/7/29 - 12:39 */public class BookDAOImplProTest { private BookDAOImpl dao = new BookDAOImpl(); @Test public void insert() { Connection connection = null; try { connection = JDBCUtils.getConnection(); Book book = new Book(1, "刘能", "LiuNeng@qq.com", new Date(201034453231L)); dao.insert(connection, book); System.out.println("插入成功"); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(connection, null); } } @Test public void deleteById() { Connection connection = null; try { connection = JDBCUtils.getConnection(); dao.deleteById(connection, 17); System.out.println("删除成功"); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(connection, null); } } @Test public void updateById() { Connection connection = null; try { connection = JDBCUtils.getConnection(); Book book = new Book(7, "夏雨而", "XY@qq.com", new Date(1242141235345L)); dao.updateById(connection, book); System.out.println(""); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(connection, null); } } @Test public void getBookById() { Connection connection = null; try { connection = JDBCUtils.getConnection(); Book book = dao.getBookById(connection, 3); System.out.println("查询成功" + book); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(connection, null); } } @Test public void getAllBooksById() { Connection connection = null; try { connection = JDBCUtils.getConnection(); ListallBooksById = dao.getAllBooksById(connection); System.out.println("查询成功"); for (Book book : allBooksById) { System.out.println(book); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(connection, null); } } @Test public void getCount() { Connection connection = null; try { connection = JDBCUtils.getConnection(); System.out.println("查询成功"); Long count = dao.getCount(connection); System.out.println("查询到的记录总数为:" + count); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(connection, null); } } @Test public void getMaxBirth() { Connection connection = null; try { connection = JDBCUtils.getConnection(); System.out.println("查询成功"); Date maxBirth = dao.getMaxBirth(connection); System.out.println("最年轻的人出生日期为:" + maxBirth); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(connection, null); } }}
4. 优化说明
1. BaseDAO类的泛型处理优化
为了解决在DAO实现类中反射获取字段名与类属性名不一致的问题,我们在BaseDAO中引入了泛型机制:
private Classclazz;{ // 获取当前BaseDAO的子类继承的父类中的泛型类型 Type genericSuperclass = this.getClass().getGenericSuperclass(); ParameterizedType pty = (ParameterizedType) genericSuperclass; // 获取父类的泛型参数(可能多个,但获取父类泛型类型就是第一个) Type[] actualTypeArguments = pty.getActualTypeArguments(); // 泽然型的第一个参数 clazz = (Class ) actualTypeArguments[0];}
通过上述方式,在子类实例化时,BaseDAO自动获取子类的泛型类型,避免了在每个实现类中手动定义泛型类型,减少了代码冗余。
2. 查询操作的优化
在查询操作中,我们采用了以下优化措施:
移除参数化的方法:将查询方法的参数从泛型化的方法中移除,改用具体的String参数,避免了泛型类型在运行时的确定问题。
统一预编译Statement:通过预编译Statement对象,减少了每次查询时的prepareStatement操作,提升了性能表现。
ResultSetMetaData优化:通过ResultSetMetaData获取列名,支持字段名与类属性名不一致的情况,提高了灵活性。
3. 事务管理优化
在增删改操作中,实现了事务管理,确保数据库连接自动提交或回滚,避免了数据库连接泄漏问题。
4. 测试验证
通过测试类验证了每个DAO操作的正确性,包括插入、删除、更新、查询等功能。每个测试方法都清晰地描述了操作内容,便于后续的功能扩展和维护。
通过以上优化方案,实现了对数据库操作的高效管理,同时保持了代码的可维护性和可扩展性。
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2025年03月30日 06时35分52秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Jupyter Notebook 暗色自定义主题
2019-03-06
[Python学习笔记]组织文件
2019-03-06
基于Redo Log和Undo Log的MySQL崩溃恢复流程
2019-03-06
从RocketMQ的Broker源码层面验证一下这两个点
2019-03-06
如何正确的在项目中接入微信JS-SDK
2019-03-06
纵览全局的框框——智慧搜索
2019-03-06
快服务流量之争:如何在快服务中占领一席之地
2019-03-06
【活动】直播揭秘<如何从0开发HarmonyOS硬件>
2019-03-06
Unity平台 | 快速集成华为性能管理服务
2019-03-06
详细实例教程!集成华为虚假用户检测,防范虚假恶意流量
2019-03-06
对模拟器虚假设备识别能力提升15%!每日清理大师App集成系统完整性检测
2019-03-06
使用Power BI构建数据仓库与BI方案
2019-03-06
pytest封神之路第二步 132个命令行参数用法
2019-03-06
Django认证系统并不鸡肋反而很重要
2019-03-06
快用Django REST framework写写API吧
2019-03-06
tep用户手册帮你从unittest过渡到pytest
2019-03-06
12张图打开JMeter体系结构全局视角
2019-03-06
Spring Boot 2.x基础教程:构建RESTful API与单元测试
2019-03-06
[UWP 自定义控件]了解模板化控件(1):基础知识
2019-03-06
UWP 自定义控件:了解模板化控件 系列文章
2019-03-06