文章目录
  1. 1. (模板方法的运用)持久层操作的java代码

(模板方法的运用)持久层操作的java代码

设计模式

第一个是操作数据库方法的抽象接口,

其实这个接口也很简单,定义了那么几个方法,说白了就是操作数据库的。

为什么要写成泛型的接口,为了就是后面大家的业务有针对性,一个实体一个业务功能类。

Java代码  -412.png

  1. package com.yd.idao;  
  2. import java.util.List;  
  3. import java.sql.Connection;  
  4. import java.sql.ResultSet;  
  5. import java.sql.SQLException;  
  6. import com.yd.support.JDataSet;  
  7. /** 
  8.  * 一个定义了所有我所需要的数据库操作的方法接口, 
  9.  * 为什么定义为抽象,我自己都搞不清楚, 
  10.  * 这里定义了泛型,这个很关键,你会看到泛型在这里的使用 
  11.  * @author kanny 
  12.  * 
  13.  * @param  
  14.  */  
  15. public abstract interface ISqlHelper {  
  16.     /** 
  17.      * 执行sql语句,大多为单句插入语句 
  18.      * @param sql   单句的sql语句 
  19.      * @param params    插入的参数 
  20.      * @param only      但为true时,sql语句为查询数量的查询语句 
  21.      * @return 
  22.      * @throws SQLException 
  23.      */  
  24.     public boolean execute(String sql, Object[] params, boolean only) throws SQLException;  
  25.     /** 
  26.      * 执行sql的批处理 
  27.      * @param sqlBatch  多条sql语句 
  28.      * @return 
  29.      * @throws SQLException 
  30.      */  
  31.     public boolean executeBatch(String[] sqlBatch) throws SQLException;  
  32.     /** 
  33.      * 执行存储过程 
  34.      * @param procName  存储过程名称 
  35.      * @param params    存储过程说需要的参数 
  36.      * @return 
  37.      * @throws SQLException 
  38.      */  
  39.     public boolean executeCall(String procName, Object[] params) throws SQLException;  
  40.     /** 
  41.      * 查询一行数据封装成java的实体 
  42.      * @param sql   sql语句 
  43.      * @param params    sql条件参数 
  44.      * @param viewName  视图名字,在查询多表关联的数据时用于区分 
  45.      * @param executeCall   是否是存储过程,如果为true,第一个sql的参数为存储过程名称 
  46.      * @return 
  47.      * @throws SQLException 
  48.      */  
  49.     public T find(String sql, Object[] params, String viewName, boolean executeCall) throws SQLException;  
  50.     /** 
  51.      * 查询多行数据封装成java的实体加入一个List里 
  52.      * @param sql   sql语句 
  53.      * @param params    sql条件参数 
  54.      * @param viewName  视图名字,在查询多表关联的数据时用于区分,循环封装实体比单一的石头封装要复杂 
  55.      * @param executeCall   是否是存储过程,如果为true,第一个sql的参数为存储过程名称 
  56.      * @return 
  57.      * @throws SQLException 
  58.      */  
  59.     public List findList(String sql, Object[] params, String viewName, boolean executeCall) throws SQLException;  
  60.     /** 
  61.      * 为了方便操作,我还特意写定义了这个返回ResultSet的方法,便于直接操作 
  62.      * @param sql 
  63.      * @param params 
  64.      * @param executeCall 
  65.      * @return 
  66.      * @throws SQLException 
  67.      */  
  68.     public ResultSet returnResultSet(String sql, Object[] params, boolean executeCall) throws SQLException;  
  69.     /** 
  70.      * 我的底层分页方法,我会给出具体代码,但这里用的只是sql server 2008的数据库分页 
  71.      * @param sql    
  72.      * @param orderby   排序列 
  73.      * @param currentPage   当前页 
  74.      * @param pageSize  每页多少行 
  75.      * @return 
  76.      * @throws SQLException 
  77.      */  
  78.     public List findListAsPager(String sql, String orderby, int currentPage, int pageSize) throws SQLException;  
  79.     /** 
  80.      * 后来为了方便操作,想朋友要来了这个JDataSet类,类似.net的DataTable的作用 
  81.      * @param sql 
  82.      * @param params 
  83.      * @param fillColumnNames   是否填充类名,请看方法代码 
  84.      * @param executeCall 
  85.      * @return 
  86.      */  
  87.     public JDataSet getJDataSet(String sql, Object[] params, boolean fillColumnNames, boolean executeCall);  
  88.     /** 
  89.      * 由于有了JDataSet这个类,于是我有写了调用这个类的分页方法 
  90.      * @param sql 
  91.      * @param orderby 
  92.      * @param currentPage 
  93.      * @param pageSize 
  94.      * @return 
  95.      * @throws SQLException 
  96.      */  
  97.     public JDataSet getJDataSetAsPager(String sql, String orderby, int currentPage, int pageSize) throws SQLException;  
  98.     /** 
  99.      * 为了方便起见,我多写了一个直接传入ResultSet而封装JDataSet的多余方法 
  100.      * @param rs 
  101.      * @param fillColumnNames 
  102.      * @return 
  103.      * @throws SQLException 
  104.      */  
  105.     public JDataSet loadJDataSet(ResultSet rs, boolean fillColumnNames) throws SQLException;  
  106.     /** 
  107.      * 得到查询数据的行数 
  108.      * @param sql 
  109.      * @return 
  110.      * @throws SQLException 
  111.      */  
  112.     public int getRowCount(String sql) throws SQLException;  
  113.     /** 
  114.      * 请看源码 
  115.      * @param rs 
  116.      * @param column 
  117.      * @return 
  118.      * @throws SQLException 
  119.      */  
  120.     public String changeFont(ResultSet rs, String column) throws SQLException;  
  121.     /** 
  122.      * 得到连接 
  123.      * @return 
  124.      * @throws SQLException 
  125.      */  
  126.     public Connection returnConn() throws SQLException;   
  127.     /** 
  128.      * 清楚所有数据库操作对象 
  129.      * @throws SQLException 
  130.      */  
  131.     public void clearAllsql() throws SQLException;   
  132. }

  

第2个类是实现这个抽象接口的抽象模版方法类

这个类最为关键,它肯定是实现了ISqlHepler.java里面的所有的方法。

其中:

protected abstract T loadDataBean(ResultSet rs, String viewName) throws SQLException;

protected abstract T loadDataBeanSelf(ResultSet rs) throws SQLException;

这2个方法是SqlHelper.java里留出来了,就是为了大家可以自己封装实体javabean来用

Java代码  %!(EXTRA markdown.ResourceType=, string=, string=)

  1. package com.yd.dao;  
  2. import java.sql.*;  
  3. import java.util.*;  
  4. import com.yd.db.DBConnPoolMgr;  
  5. import com.yd.idao.ISqlHelper;  
  6. import com.yd.support.JDataSet;  
  7. public abstract class SqlHelper implements ISqlHelper {  
  8.     protected java.sql.Connection conn = null;  
  9.     protected java.sql.PreparedStatement pst = null;  
  10.     protected java.sql.Statement st = null;  
  11.     protected java.sql.CallableStatement cs = null;  
  12.     protected java.sql.ResultSet rs = null;  
  13.     protected java.sql.ResultSetMetaData rm = null;  
  14.     public Connection returnConn() throws SQLException {  
  15.                   //DBConnPoolMgr是自己写的一个简单连接池类,用来得到连接,我后面会给出这个类的代码  
  16.         return (conn = DBConnPoolMgr.getInctence().getConnect());  
  17.     }  
  18.     private PreparedStatement returnPst(String sql, Object[] params) throws SQLException {  
  19.         if (conn == null || conn.isClosed()) conn = returnConn();  
  20.         pst = conn.prepareStatement(sql);  
  21.         if (params != null)  
  22.             for (int i = 0; i < params.length; i++)  
  23.                 pst.setObject(i + 1, params[i]);  
  24.         return pst;  
  25.     }  
  26.     protected CallableStatement returnCs(String procName, Object[] params) throws SQLException {  
  27.         if (conn == null || conn.isClosed()) conn = returnConn();  
  28.         String call = “”;  
  29.         if (params != null) {  
  30.             call = “{call “ + procName + “(“;  
  31.             for (int c = 0; c < params.length - 1; c++)  
  32.                 call += “?,”;  
  33.             call += “?)}”;  
  34.         } else  
  35.             call = “{call “ + procName + “()}”;  
  36.         cs = conn.prepareCall(call);  
  37.         if (params != null)  
  38.             for (int i = 0; i < params.length; i++)  
  39.                 cs.setObject(i + 1, params[i]);  
  40.         return cs;  
  41.     }  
  42.     public void clearAllsql() {  
  43.         try   
  44.         {   
  45.             if (rs != null) rs.close();  
  46.             if (cs != null) cs.close();  
  47.             if (st != null) st.close();  
  48.             if (pst != null) pst.close();  
  49.             if (conn != null) {  
  50.                 DBConnPoolMgr.getInctence().returnConnect(conn);  
  51.             }  
  52.             rs = null;  
  53.             cs = null;  
  54.             st = null;  
  55.             pst = null;  
  56.         }   
  57.         catch (SQLException ex) { ex.printStackTrace(); }  
  58.     }  
  59.     public boolean execute(String sql, Object[] params, boolean only) {  
  60.         boolean bVal = false;  
  61.         try   
  62.         {  
  63.             if (only) {  
  64.                 rs = returnPst(sql, params).executeQuery();  
  65.                 while (rs.next()) bVal = true;  
  66.             } else {  
  67.                 returnPst(sql, params).executeUpdate();  
  68.                 bVal = true;  
  69.             }  
  70.         }   
  71.         catch (SQLException ex) { ex.printStackTrace(); }   
  72.         finally { clearAllsql(); }  
  73.         return bVal;  
  74.     }  
  75.     public boolean executeBatch(String[] sqlBatch) {  
  76.         boolean bVal = false;  
  77.         try   
  78.         {  
  79.             conn = returnConn();  
  80.             st = conn.createStatement();  
  81.             boolean autoCommit = conn.getAutoCommit();  
  82.             for (int i = 0; i < sqlBatch.length; i++) {  
  83.                 if (sqlBatch[i] != null && !sqlBatch[i].equals(“”))  
  84.                     st.addBatch(sqlBatch[i] + “;”);  
  85.             }  
  86.             conn.setAutoCommit(false);  
  87.             st.executeBatch();  
  88.             conn.commit();  
  89.             conn.setAutoCommit(autoCommit);  
  90.             bVal = true;  
  91.         }   
  92.         catch (SQLException ex) {  
  93.             try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); }  
  94.             ex.printStackTrace();  
  95.         } finally { clearAllsql(); }  
  96.         return bVal;  
  97.     }  
  98.     public boolean executeCall(String procName, Object[] params) {  
  99.         boolean bVal = false;  
  100.         try   
  101.         {  
  102.             returnCs(procName, params).executeUpdate();  
  103.             bVal = true;  
  104.         }   
  105.         catch (Exception ex) { ex.printStackTrace(); }   
  106.         finally { clearAllsql(); }  
  107.         return bVal;  
  108.     }  
  109.     public T find(String sql, Object[] params, String viewName, boolean executeCall) {  
  110.         T t = null;  
  111.         try   
  112.         {  
  113.             if (executeCall) rs = returnCs(sql, params).executeQuery();  
  114.             else rs = returnPst(sql, params).executeQuery();  
  115.             t = loadResultSet(rs, viewName);  
  116.         }   
  117.         catch (Exception ex) { ex.printStackTrace(); }   
  118.         finally { clearAllsql(); }  
  119.         return t;  
  120.     }  
  121.     public List findList(String sql, Object[] params, String viewName, boolean executeCall) {  
  122.         List lt = null;  
  123.         try   
  124.         {  
  125.             if (executeCall) rs = returnCs(sql, params).executeQuery();  
  126.             else rs = returnPst(sql, params).executeQuery();  
  127.             lt = loadList(rs, viewName);  
  128.         }   
  129.         catch (Exception ex) { ex.printStackTrace(); }   
  130.         finally { clearAllsql(); }  
  131.         return lt;  
  132.     }  
  133.     public ResultSet returnResultSet(String sql, Object[] params, boolean executeCall) {  
  134.         try   
  135.         {  
  136.             if (executeCall) rs = returnCs(sql, params).executeQuery();  
  137.             else rs = returnPst(sql, params).executeQuery();  
  138.         }   
  139.         catch (Exception ex) { ex.printStackTrace(); }  
  140.         return rs;  
  141.     }  
  142.     private T loadResultSet(ResultSet rs, String viewName) throws SQLException {  
  143.         T t = null;  
  144.         if (rs != null) while (rs.next()) t = loadDataBean(rs, viewName);  
  145.         return t;  
  146.     }  
  147.     private List loadList(ResultSet rs, String viewName) throws SQLException {  
  148.         List tlist = new ArrayList();  
  149.         if (rs != null)   
  150.             while (rs.next())   
  151.                 tlist.add(loadDataBean(rs, viewName));  
  152.         return tlist;  
  153.     }  
  154.     public String changeFont(ResultSet rs, String column) throws SQLException {  
  155.         return rs.getString(column) == null ? “” : rs.getString(column);  
  156.     }  
  157.     public int returnColumnCount(ResultSet rs) throws SQLException {  
  158.         return rs.getMetaData().getColumnCount();  
  159.     }  
  160.          //两个非常关键的模版方法,继承此类的操作类都要实现这2个方法,我到时候会给出操作类  
  161.     protected abstract T loadDataBean(ResultSet rs, String viewName) throws SQLException;  
  162.     protected abstract T loadDataBeanSelf(ResultSet rs) throws SQLException;  
  163.     public List findListAsPager(String sql, String orderby, int currentPage, int pageSize) {  
  164.         List lt = null;  
  165.         try   
  166.         {  
  167.             String strVal = strPager(sql, orderby, currentPage, pageSize);  
  168.             rs = returnPst(strVal, null).executeQuery();  
  169.             lt = loadList(rs, “”);  
  170.         }   
  171.         catch (SQLException ex) { ex.printStackTrace(); }   
  172.         finally { clearAllsql(); }  
  173.         return lt;  
  174.     }  
  175.          //因为用的sql server 2008所以只写了这个数据库的分页  
  176.     private String strPager(String sql, String orderby, int currentPage, int pageSize) {  
  177.         int start = 1;  
  178.         if (currentPage > 1) start = (currentPage - 1) * pageSize + 1;  
  179.         int end = start + pageSize - 1;  
  180.         String sqlColumn = “*”;  
  181.         String sqlDo = “”;  
  182.         if(sql.indexOf(“@#”) != -1) {  
  183.             String []sqlArr = sql.split(“@#”);  
  184.             sqlColumn = sqlArr[0];  
  185.             sqlDo = sqlArr[1];  
  186.         } else {  
  187.             sqlColumn = “*”;  
  188.             sqlDo = sql;  
  189.         }  
  190.         String strVal = “select * from (select “ + sqlColumn + “,ROW_NUMBER()”;  
  191.         strVal += “ Over(order by “ + orderby + “)”;  
  192.         strVal += “ as rowNum “ + sqlDo + “)”;  
  193.         strVal += “ as myTable where rowNum between “ + start + “ and “ + end;  
  194.         return strVal;  
  195.     }  
  196.     public int getRowCount(String sql) throws SQLException {  
  197.         String sqlDo = “”;  
  198.         if(sql.indexOf(“@#”) != -1) {  
  199.             String []sqlArr = sql.split(“@#”);  
  200.             sqlDo = sqlArr[1];  
  201.         } else sqlDo = sql;  
  202.         int count = 0;  
  203.         try   
  204.         {  
  205.             rs = this.returnResultSet(“select count(*) “ + sqlDo, null, false);  
  206.             while (rs.next()) count = rs.getInt(1);  
  207.         }   
  208.         catch (Exception ce) { ce.printStackTrace();}   
  209.         finally { clearAllsql(); }  
  210.         return count;  
  211.     }  
  212.     public JDataSet getJDataSetAsPager(String sql, String orderby, int currentPage, int pageSize) {  
  213.         String strVal = strPager(sql, orderby, currentPage, pageSize);  
  214.         return getJDataSet(strVal, null, true, false);  
  215.     }  
  216.     public JDataSet getJDataSet(String sql, Object[] params, boolean fillColumnNames, boolean executeCall) {  
  217.         JDataSet jds = null;  
  218.         try   
  219.         {  
  220.             if (executeCall) rs = returnCs(sql, params).executeQuery();  
  221.             else rs = returnPst(sql, params).executeQuery();  
  222.             jds = loadJDataSet(rs, fillColumnNames);  
  223.         }   
  224.         catch (Exception ex) { ex.printStackTrace(); }   
  225.         finally { clearAllsql(); }  
  226.         return jds;  
  227.     }  
  228.     public JDataSet loadJDataSet(ResultSet rs, boolean fillColumnNames) {  
  229.         JDataSet jds = new JDataSet();  
  230.         try   
  231.         {  
  232.             int columnCount = returnColumnCount(rs);  
  233.             if (fillColumnNames) {  
  234.                 String[] columnNames = new String[columnCount];  
  235.                 String[] columnTypeNames = new String[columnCount];  
  236.                 for (int i = 0; i < columnCount; i++) {  
  237.                     columnNames[i] = rs.getMetaData().getColumnName(i + 1);  
  238.                     columnTypeNames[i] = rs.getMetaData().getColumnTypeName(i + 1);  
  239.                 }  
  240.                 jds.setColumnNames(columnNames);  
  241.                 jds.setColumnTypeNames(columnTypeNames);  
  242.             }  
  243.             while (rs.next()) {  
  244.                 String[] row = new String[columnCount];  
  245.                 for (int i = 0; i < columnCount; i++)  
  246.                     row[i] = rs.getString(i + 1) == null ? “” : rs.getString(i + 1).trim();  
  247.                 jds.addRow(row);  
  248.             }  
  249.         }   
  250.         catch (Exception ex) { ex.printStackTrace(); }  
  251.         return jds;  
  252.     }  
  253. }

  

现在来说下怎么用这个类

比如,你有一个学生类Student.java里面有id,name,age3个属性

Java代码  %!(EXTRA markdown.ResourceType=, string=, string=)

  1. public Class Student  
  2. {  
  3.     private int id;  
  4.     private String name;  
  5.     private int age;  
  6.     以下get和set方法省略…  
  7. }

  

你要封装它,你就可以自己定义一个IStudent.java接口extends那个ISqlHelper.java接口

然后来里面定义插入,查询全部,和按id查的功能函数,象如下写的一样

<

当然这样定义很死,最好的方法,就是整理抽象出所有业务类的公用方法,比如,插入,修改,删除。

然后把这些方法在一个公用的操作接口中定义,这个公用的操作接口可以继承ISqlHelper.java接口

然后以后业务类或是数据实体操作类都可以实现这个公用的操作接口。

Java代码  %!(EXTRA markdown.ResourceType=, string=, string=)

  1. public interface IStudent extends ISqlHelper  
  2. {  
  3.     //插入Student  
  4.     public boolean insertStudent(Student stu);  
  5.     //查询全部Student  
  6.     public List findStudent();  
  7.     //按id查询某一个Student  
  8.     public Student findStudentAsId(int stuid);  
  9. }

  

并写一个StudentBO.java业务类extends那个SqlHelper和自己定义的IStudent接口

象如下写的一样:

Java代码  %!(EXTRA markdown.ResourceType=, string=, string=)

  1. public Class StudentBO extends SqlHelper implements IStudent  
  2. {  
  3.     protected Student loadDataBean(ResultSet rs, String viewName) throws SQLException;  
  4.     {  
  5.         Student stu = loadDataBeanSelf(ResultSet rs);  
  6.         return stu;  
  7.     }  
  8.     protected Student loadDataBeanSelf(ResultSet rs) throws SQLException;  
  9.     {  
  10.         Student stu = new Student();  
  11.         stu.setId(rs.getInt(“id”));  
  12.         stu.setName(rs.changeFont(rs,”name”));  
  13.         stu.setAge(rs.getInt(“age”));  
  14.         return stu;  
  15.     }  
  16.     //实现:插入Student的函数  
  17.     public boolean insertStudent(Student stu)  
  18.     {  
  19.         String sql = “insert into Student(id,name,age) values(?,?,?)”;  
  20.         Object [] params = new Object[]{stu.getId(),stu.getName,stu.getAge};  
  21.         return this.execute(sql, params, false);  
  22.     }  
  23.     //实现:查询全部Student  
  24.     public List findStudent()  
  25.     {  
  26.         String sql = “select * from Student”;  
  27.         return this.findList(sql, null, “”,false);  
  28.     }  
  29.     //实现:按id查询某一个Student  
  30.     public Student findStudentAsId(int stuid)  
  31.     {  
  32.         String sql = “select * from Student where id=” + stuid;  
  33.         return this.find(sql, null, “”,false);  
  34.     }  
  35. }

  

loadDataBean,loadDataBeanSelf是从SqlHelper里继承下来的抽象方法。

必须实现。这就是利用了模版方法模式写出来的。

也就是说,以后你自己写函数的时候,只要在接口里定义,

然后在这样的BO类里写实现它,而且就写那么一点语句就完成了。大大省时省力。

好了这样就完成了,代码是不是看上去又清楚又整洁,如果查找和维护。而且大大减少了那些功能代码和封装象Student.java这样数据实体的代码。一次封装无须在写。

大家肯定有疑问,那就是

this.execute

this.findList

this.find

三个函数哪来的,里面都做了些什么

首先要说他们3个肯定是SqlHelper里被实现过的函数

至于他们怎么实现的,你仔细看下就全明白了。

为什么要多出一个loadDataBean来,大家都看到了,他有一个参数viewName,这里就是用到这个参数的地方,因为大家操作数据库不 可能就是那么一张表的操作,有时候会有2到3张表联查,那么用这个参数来判断是哪个函数查出不一样的结果,那么你在这个函数里利用这个参数引进别的 xxxBO的loadDataBeanSelf函数,不就可以不用再次重新写那些讨厌的实体封装代码了吗。重用性大大提升。

注意一点,这里的查询是只能全查,如果只需要几个字段,就只能手动自己写咯,其实我是想写一个通用的想查几个字段就几个字段的封装方法,但我懒,所以到现在都没去写

其实还有很多应用和问题,这些我在这里也说不完,希望大家多多交流。

我还会给出我自己当初写的数据库连接池类,希望这些简单的代码能给java新手以帮助。

而且如果大家觉得有问题有意义,一定要发帖指出。哪里好哪里不好

希望大家多多给出看法,多多益善。

在这里还要感谢论坛中yangguo兄,其实我当时写这段代码的主要目的

就是dbutils框架所实现的一个最重要功能

只提交sql语句,然后的数据自动填充到所需要的实体中。而不要在写那么多繁琐的实体封装代码。

这个是源码例子,希望大家能明白这样写的用意,值得探讨。

文章目录
  1. 1. (模板方法的运用)持久层操作的java代码