使用JDBC操作数据库时,dao层的增删改查有很多重复的代码,比如下面的

  1. public int getTotal() {
  2. Connection conn = null;//通用代码
  3. PreparedStatement ps = null;//通用代码
  4. ResultSet rs = null;//通用代码
  5. try {
  6. conn = ...//获取连接//通用代码
  7. ps = conn.prepareStatement("select count(*) from blog");//只有sql语句不同
  8. rs = ps.executeQuery();
  9. if (rs.next()) {
  10. return rs.getInt(1);
  11. }
  12. } catch (SQLException e) {
  13. e.printStackTrace();
  14. } finally {
  15. try {
  16. rs.close();//通用代码
  17. ps.close();//通用代码
  18. conn.close();//通用代码
  19. } catch (SQLException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. return 0;
  24. }

如果做一个简单的增删改查,会发现很多代码都是通用的,如果重复使用无疑会让代码显得很冗余

如果使用框架开发,框架会帮我们省去这些麻烦,或者有很多开源的工具类也可以比如apache的DBUtil工具类

不过看了黑马的教学视频,感觉完全可以自定义一个JDBC框架来帮我们省去很多麻烦(虽然我是造轮子,不过学习初期造轮子还是很有帮助的)

自定义JDBC框架

对于增删改里面重复的代码最多,且不包含结果集(查询包含的结果集需要封装,所以单独定义),用update方法统一代表增删改,query方法代表查询

对于过程,我们发现用JDBC增删改查里面只有sql语句不一样,sql语句里的占位符又会不一样,所以考虑自定义方法里传入参数包含sql语句和sql语句中需要传入的参数(用数组表示),对于查询由于需要封装结果集到Bean中,但是Bean类实现不知道,所以无法直接封装,考虑使用策略模式

下面直接上代码,具体解释留在注释中

由于使用了DBCP数据源,所以用的DBCP数据源获取数据库连接,这里就不上DBCP的代码了

主类DBAssist

  1. public class DBAssist {
  2. //设置连接从数据源获取
       //也可以不使用数据源,自己随便定义个Connection连接 
  3. private DataSource ds;
  4. public DBAssist(DataSource ds){
  5. this.ds=ds;
  6. }
  7. //增删改
  8. public void update(String sql,Object[] params){
  9. Connection conn=null;
  10. PreparedStatement ps=null;
  11. ResultSet rs=null;
  12. try{
  13. conn=ds.getConnection();//得到链接
  14. ps=conn.prepareStatement(sql);
  15. //设置参数,
  16. //ParameterMetaData方法获取参数信息
  17. ParameterMetaData pmd=ps.getParameterMetaData();
  18. //获取sql语句中的占位符?个数
  19. int parameterCount=pmd.getParameterCount();
  20. //获取的参数个数与传入的参数个数比较
  21. if(parameterCount>0){
  22. if(params==null||params.length<1)
  23. throw new IllegalArgumentException("the parameter is wrong");
  24. if(params.length!=parameterCount)
  25. throw new IllegalArgumentException("the parameter is wrong");
  26. for(int i=0;i<parameterCount;i++){
  27. ps.setObject(i+1, params[i]);
  28. }
  29. }
  30. ps.executeUpdate();
  31. }catch(Exception e){
  32. throw new DBAssistException(e);
  33. }finally{
  34. release(conn,ps,rs);
  35. }
  36. }
  37. //查询,由于不知道具体的Bean类,考虑使用策略模式
  38. //ResultSetHandler为抽象出的策略接口,策略类需继承该类以完成封装
  39. //策略类框架会给出实现
  40. public Object query(String sql,Object[] params,ResultSetHandler rsh){
  41. Connection conn=null;
  42. PreparedStatement ps=null;
  43. ResultSet rs=null;
  44. try{
  45. conn=ds.getConnection();
  46. ps=conn.prepareStatement(sql);
  47. ParameterMetaData pmd=ps.getParameterMetaData();
  48. int parameterCount=pmd.getParameterCount();//sql语句中的占位符个数
  49. if(parameterCount>0){
  50. if(params==null||params.length<1)
  51. throw new IllegalArgumentException("the parameter is wrong");
  52. if(params.length!=parameterCount)
  53. throw new IllegalArgumentException("the parameter is wrong");
  54. for(int i=0;i<parameterCount;i++){
  55. ps.setObject(i+1, params[i]);
  56. }
  57. }
  58. //得到查询结果集
  59. rs=ps.executeQuery();
  60. //封装结果集到对象中去,这里使用策略模式,最好提供实现类(类似于注册器)
  61. return rsh.handler(rs);
  62. }catch(Exception e){
  63. throw new DBAssistException(e);
  64. }finally{
  65. release(conn,ps,rs);
  66. }
  67. }
  68. //关闭连接
  69. private void release(Connection conn,Statement stmt,ResultSet rs){
  70. if(rs!=null){
  71. try {
  72. rs.close();
  73. } catch (SQLException e) {
  74. e.printStackTrace();
  75. }
  76. rs=null;
  77. }
  78. if(stmt!=null){
  79. try {
  80. stmt.close();
  81. } catch (SQLException e) {
  82. e.printStackTrace();
  83. }
  84. stmt=null;
  85. }
  86. if(conn!=null){
  87. try {
  88. conn.close();
  89. } catch (SQLException e) {
  90. e.printStackTrace();
  91. }
  92. conn=null;
  93. }
  94. }
  95. }

此时已经可以用update方法进行增删改的功能了

对于查询,query方法中的策略接口代码如下

  1. public interface ResultSetHandler {
  2. public Object handler(ResultSet rs);
  3. }

具体策略类有两个,分别用来查询单行和查询多行(利用反射填充Bean中的字段)

  1. public class BeanHandler implements ResultSetHandler {
  2. private Class<? extends Object> clazz;
  3.  
  4. public BeanListHandler(Class<? extends Object> clazz) {
  5. this.clazz = clazz;
  6. }
  7.  
  8. public List<Object> handler(ResultSet rs) {
  9. try {
  10. List<Object> list = new ArrayList<Object>();
  11. while (rs.next()) {
  12. Object bean = clazz.newInstance();
              //查询数据库中的元数据信息
  13. ResultSetMetaData rsmd = rs.getMetaData();
  14. int count = rsmd.getColumnCount();
  15. for (int i = 0; i < count; i++) {
  16. String columnName = rsmd.getColumnName(i + 1);
  17. Object columnValue = rs.getObject(i + 1);
  18. Field field = clazz.getDeclaredField(columnName);
  19. field.setAccessible(true);
  20. field.set(bean, columnValue);
  21. }
  22. list.add(bean);
  23. }
  24. return list;
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. }
  28. return null;
  29. }
  30.  
  31. }

  1. //bean中字段名必须与数据库中字段名一致
  2. public class BeanListHandler implements ResultSetHandler {
  3. private Class<? extends Object> clazz;
  4. public BeanHandler(Class<? extends Object> clazz) {
  5. this.clazz=clazz;
  6. }
  7. //查询单记录
  8. public Object handler(ResultSet rs) {
  9. try {
  10. Object bean=clazz.newInstance();
  11. if(rs.next()){
            
  12. ResultSetMetaData rsmd=rs.getMetaData();
  13. int count=rsmd.getColumnCount();
  14. for(int i=0;i<count;i++){
  15. String columnName=rsmd.getColumnName(i+1);
  16. Object columnValue=rs.getObject(i+1);
  17. Field field=clazz.getDeclaredField(columnName);
  18. field.setAccessible(true);
  19. field.set(bean,columnValue);
  20. }
  21. return bean;
  22. }
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. }
  26. return null;
  27. }
  28. }

Bean类

  1. public class Blog {
  2. private int id;
  3. private int category_id;
  4. private String title;
  5. private String content;
  6. private Date created_time;
       ...
       //getter和setter方法
  7. @Override
  8. public String toString() {
  9. return "Blog [id=" + id + ", category_id=" + category_id + ", title=" + title + ", content=" + content
  10. + ", created_time=" + created_time + "]";
  11. }
  12.  
  13. }

自定义异常类

  1. public class DBAssistException extends RuntimeException {
  2.  
  3. public DBAssistException() {
  4. }
  5.  
  6. public DBAssistException(String message) {
  7. super(message);
  8. }
  9.  
  10. public DBAssistException(Throwable cause) {
  11. super(cause);
  12. }
  13.  
  14. public DBAssistException(String message, Throwable cause) {
  15. super(message, cause);
  16. }
  17.  
  18. public DBAssistException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
  19. super(message, cause, enableSuppression, writableStackTrace);
  20. }
  21.  
  22. }

最后测试下

  1.   public void update(){
  2. String sql="update blog set created_time=? where id=?";
  3. dba.update(sql, new Object[]{new Date(System.currentTimeMillis()),1});
  4. }
       //查询单行记录测试
  5. public void query(){
  6. String sql="select * from blog";
  7. Blog blog=(Blog) dba.query(sql, null,new BeanHandler(Blog.class));
  8. System.out.println(blog.getTitle().length());
  9. }
       //查询多行记录测试
  10. @SuppressWarnings("unchecked")
  11. public List<Blog> query2(){
  12. String sql="select * from blog";
  13. List<Blog> list=(List<Blog>) dba.query(sql, null,new BeanListHandler(Blog.class));
  14. return list;
  15. }
  16. public static void main(String args[]) {
  17. BlogDao test = new BlogDao();System.out.println(test.update());
  18. test.query();
  19. List<Blog> list=test.query2();
  20. for(Blog l:list){
  21. System.out.println(l);
  22. }
  23. }
  24. }

实现自己的JDBC框架的更多相关文章

  1. java web学习总结(二十三) -------------------编写自己的JDBC框架

    一.元数据介绍 元数据指的是"数据库"."表"."列"的定义信息. 1.1.DataBaseMetaData元数据 Connection.g ...

  2. Spring的JDBC框架

    转自: http://www.cnblogs.com/windlaughing/p/3287750.html Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发. Spring主要 ...

  3. 【总结】编写自己的JDBC框架

    一.数据库连接池: 在一般用JDBC 进行连接数据库进行CRUD操作时,每一次都会: 通过:java.sql.Connection conn = DriverManager.getConnection ...

  4. jdbc框架 commons-dbutils+google guice+servlet 实现一个例子

    最近闲着无聊,于是看了一下jdbc框架 commons-dbutils与注入google guice. 我就简单的封装了一下代码,效率还是可以的.... jdbc+google guice+servl ...

  5. JDBC 学习笔记(四)—— 自定义JDBC框架+Apache—DBUtils框架+事务管理+操作多表

    本文目录:       1.自定义JDBC框架 ——数据库元数据:DataBaseMetaData        2.自定义JDBC框架 ——数据库元数据:DataBaseMetaData       ...

  6. javaweb学习总结(四十)——编写自己的JDBC框架

    一.元数据介绍 元数据指的是"数据库"."表"."列"的定义信息. 1.1.DataBaseMetaData元数据 Connection.g ...

  7. JDBC框架

    一.元数据介绍 元数据指的是"数据库"."表"."列"的定义信息. 1.1.DataBaseMetaData元数据 Connection.g ...

  8. 编写自定义的JDBC框架与策略模式

    本篇根据上一篇利用数据库的几种元数据来仿造Apache公司的开源DbUtils工具类集合来编写自己的JDBC框架.也就是说在本篇中很大程度上的代码都和DbUtils中相似,学完本篇后即更容易了解DbU ...

  9. 黑马程序员—创建JDBC框架及原理分析

    对于Java数据库的连接,由最初学习的每次全部手工代码,到后面的不断利用知识简化代码量:这是不断学习的过程,就像人类由原始社会的钻木取火到当代的文明,都是一步步过来的! 本文不从最开始的JDBC入门开 ...

随机推荐

  1. PLinq

    PLinq(Linq的并行计算) 上面介绍完了For和ForEach的并行计算盛宴,微软也没忘记在Linq中加入并行计算.下面介绍Linq中的并行计算. 4.0中在System.Linq命名空间下加入 ...

  2. POCO Controller

    ---恢复内容开始--- POCO Controller 你这么厉害,ASP.NET vNext 知道吗?   写在前面 阅读目录: POCO 是什么? 为什么会有 POJO? POJO 的意义 PO ...

  3. .NET核心代码保护策略

    .NET核心代码保护策略-隐藏核心程序集 经过之前那个道德指责风波过后也有一段时间没写博客了,当然不是我心怀内疚才这么久不写,纯粹是程序员的通病..怎一个懒字了得,本来想写一些长篇大论反讽一下那些道德 ...

  4. 【Yom框架】漫谈个人框架的设计之二:新的IRepository接口+搜索和排序解耦(+基于Castle实现)

    经过了上篇IRepository和IRepository<T>的讨论[文章地址为:http://www.cnblogs.com/yomho/p/3296759.html] 我选择了IRep ...

  5. JS判断字符串是否包含某字符串 indexOf()方法使用

    定义和用法 indexOf()方法可返回某个指定的字符串值在字符串中首次出现的位置. 开始的.如果没有找到子字符串,则返回 -1. 示例: <script type="text/jav ...

  6. uva 408 Uniform Generator

    Uniform Generator  Computer simulations often require random numbers. One way to generate pseudo-ran ...

  7. 设置启动MyEclipse8.5的时候选择工作区间

    以前我的MyEclipse启动的时候默认都会进入到指定工作区间,比如:D:\MyEclipse,最近不知道怎么回事,每次启动的时候都是空的,必须要重新Switch Workspace选择一次 网上查找 ...

  8. AspxTreeList获取选中项的值

    在csdn上了发了次帖子,没人回复,只有自己结贴了.http://bbs.csdn.net/topics/390706314?page=1#post-396723432 //通过选中的节点获取用户ID ...

  9. iOS 7 beta4 体验

    iOS 7 beta4终于来了,安装后感觉稳定了不少.下面列几点我个人感受比较深得地方. 1.锁屏界面有滑动方向箭头了,而且“滑动来解锁”几个字也有动态颜色变化,让人不再迷惑该往那边滑动了. 2.通知 ...

  10. 一步步学习Python-django开发-建立django数据库

    上篇文章建立了一个空的网站.现在我们要准备正式我们的网站开发咯.那么开发的第一步是啥呢?当然是要确定做什么网站了.每个人的开发习惯可能不尽相同,有点可能是从前端开始设计,有的可能是从数据库开始设计(不 ...