现在的位置: 首页 > 综合 > 正文

commons-dbutils轻量级JDBC数据库规范

2018年05月28日 ⁄ 综合 ⁄ 共 9267字 ⁄ 字号 评论关闭

 业内流行这么一句话:"三流公司卖产品;二流公司卖服务;一流公司卖标准." 
    标准就是规范,所以开发中,最难的不是具体功能的实现,而是制定一个开发规范,大家共同去遵守.废话不说了,直接进入正题^-^ 
一 介绍 
    commons是apache旗下一个著名的开源项目.他提供了很多方便使用的工具类.今天之所以把标题命名为,是因为相对于方便的工具来说,commons-dbutils的更大意义在于JDBC的开发规范.这样增强了代码的可读性和维护性.本文的出发点也是从规范说起,捎带着一些常用的方法. 
    commons-dbutils是一个轻量级的JDBC开发框架.里面只是一些非常简单的封装.下面笔者先介绍几个常用的类和接口. 
    1)org.apache.commons.dbutils.DbUtils.java 
这个类提供了数据库初始化和关闭相关的初始操作.包括资源的开关,驱动的加载.事务回滚等常用操作。 
    public static void closeQuietly(Connection conn, Statement stmt, 
            ResultSet rs) { 
        try { 
            closeQuietly(rs); 
        } finally { 
            try { 
                closeQuietly(stmt); 
            } finally { 
                closeQuietly(conn); 
            } 
        } 
    } 
这个方法,提供了对Connection,Statement/PrepareStatement,ResultSet的关闭操作.只需要一行代码,就可以安全的关闭.其中具体的细节,大家可以更深入的阅读源代码. 
    public static void commitAndClose(Connection conn) throws SQLException { 
        if (conn != null) { 
            try { 
                conn.commit(); 
            } finally { 
                conn.close(); 
            } 
        } 
    } 
    这个接口是先提交,后关闭. 
    2)org.apache.commons.dbutils.QueryRunner.java 

Java代码  收藏代码
  1. Object[][] params = new Object[vars.size()][5];  
  2. Var var = new Var();  
  3. int count = 0;  
  4. String sql = "";  
  5. count = vars.size();  
  6. // 组装参数  
  7. for (int i = 0; i < count; i++) {  
  8.     var = vars.get(i);  
  9.     params[i][0] = var.getDate_Time();  
  10.     params[i][1] = var.getId();  
  11.     params[i][2] = var.getValue_t();  
  12.     params[i][3] = var.getDate_Time();  
  13.     params[i][4] = var.getId();  
  14. }  
  15. // 执行批处理  
  16. sql = "insert into vardata(time,name,data) select ?,?,? from dual where not exists (select * from vardata where time=? and name=?)";  
  17. run.batch(sql, params);  

上面是一个批处理的例子,这个类提供了相当强大的查询功能,可以类似ORM一样,使用查询. 
二 项目应用 
    1)背景:本人正在从事的项目中,有个数据采集的功能.在SQL SERVER 2005中,只存在1个表,表中有2个字段.这个表只有185条纪录.每天纪录代表一个变量.2个字段分别为name,value.想必读者一看就能明白字段的含义.为了保证硬件设备WINCC的性能,所以他不会把数据累积到SQL
SERVER 2005中,而只是刷新185条记录.所以数据库中,永远只有185条数据.因此我们需要实现个功能,每5秒钟到SQL SERVER 2005中,拿到全部数据,保存在一个可以累积历史数据的库中来.本项目中,我们选择MySQL5.1.49,通过对时间字段分区,实现了大量数据高性能的需求.下面笔者只演示commons-dbutils相关的部分,其中MySQL的数据库结构,也被笔者简化. 

    2)环境: 
数据库: 
MySQL 5.1.49 
JDK环境: 
6.0.21 
数据源: 
commons-dbcp 
commons-pool 
    3)数据库: 

Sql代码  收藏代码
  1. CREATE DATABASE `test`;   
  2. CREATE TABLE `icerecord` (   
  3.   `id` int(11) NOT NULL AUTO_INCREMENT,   
  4.   `value_t` float(10,5) DEFAULT '0.00000',   
  5.   `Date_Time` varchar(50) DEFAULT '',   
  6.   PRIMARY KEY (`id`)   
  7. ) ;   
  8. INSERT INTO `icerecord` VALUES (1,100,'2010-07-31');   
  9. INSERT INTO `icerecord` VALUES (2,200,'2010-07-30');   
  10. INSERT INTO `icerecord` VALUES (3,300,'2010-07-29');   
  11. INSERT INTO `icerecord` VALUES (4,400,'2010-07-28');   
  12. INSERT INTO `icerecord` VALUES (5,500,'2010-07-27');   
  13. INSERT INTO `icerecord` VALUES (6,600,'2010-07-26');   


    4)代码 
    DBBase类中演示了如何通过commons-dbutils来操纵数据源.其中应用了类似ORM的思想.List vars = DBBase.getInstance().queryForOList(sql, null, Var.class);这行代码使用时需要注意: 
   1)Var与数据库中的表icerecord是映射关系,但名字不需要一样; 
   2)Var中的属性和类型,要与数据库中的字段类型保持一致; 
   3)Var中的属性要用标准的getter和setter. 
具备了上述3个条件,调用queryForOList方法后,commons-dbutils会自动将查询结果进行封装成List. 
   笔者也进行了对比实验,使用commons-dbutils封装对象,比自行getter&amp;setter的效率高出20倍.传统方法查询后(185条记录)自行封装,需要370毫秒,而使用commons,仅需要23毫秒. 
   下面也包含了Var类.所有代码经过本人亲自运行测试.希望对大家有所帮助. 

Java代码  收藏代码
  1. package test.common.db;  
  2.   
  3. import java.sql.SQLException;  
  4. import java.util.List;  
  5.   
  6. import javax.sql.DataSource;  
  7.   
  8. import org.apache.commons.dbcp.BasicDataSource;  
  9. import org.apache.commons.dbutils.QueryRunner;  
  10. import org.apache.commons.dbutils.handlers.BeanHandler;  
  11. import org.apache.commons.dbutils.handlers.BeanListHandler;  
  12. import org.apache.commons.dbutils.handlers.ScalarHandler;  
  13.   
  14. public class DBBase {  
  15.   
  16.     private static DBBase dbBase;  
  17.   
  18.     private static QueryRunner run;  
  19.   
  20.     private DataSource dataSource;  
  21.   
  22.     public DataSource getDataSource() {  
  23.         return dataSource;  
  24.     }  
  25.   
  26.     public void setDataSource(DataSource dataSource) {  
  27.         this.dataSource = dataSource;  
  28.     }  
  29.   
  30.     private DBBase() {  
  31.     }  
  32.   
  33.     private void init() {  
  34.         dbBase = this;  
  35.         run = new QueryRunner(dataSource);  
  36.     }  
  37.   
  38.     public static DBBase getInstance() {  
  39.         return dbBase;  
  40.     }  
  41.   
  42.     /** 
  43.      * eg: select count(1) from user 
  44.      *  
  45.      * @param sql 
  46.      * @param params 
  47.      * @return 
  48.      */  
  49.     public int count(String sql, Object[] params) {  
  50.   
  51.         Object o = getAnAttr(sql, params);  
  52.         if (o instanceof Integer) {  
  53.             return (Integer) o;  
  54.         }  
  55.         if (o instanceof Long) {  
  56.             Long l = (Long) o;  
  57.             return l.intValue();  
  58.         }  
  59.   
  60.         String s = (String) o;  
  61.         try {  
  62.             return Integer.parseInt(s);  
  63.         } catch (NumberFormatException e) {  
  64.             return 0;  
  65.         }  
  66.     }  
  67.   
  68.     /** 
  69.      * 获得第一个查询第一行第一列 
  70.      *  
  71.      * @param sql 
  72.      * @param params 
  73.      * @return 
  74.      */  
  75.     public Object getAnAttr(String sql, Object[] params) {  
  76.   
  77.         showSql(sql);  
  78.   
  79.         Object s = null;  
  80.         try {  
  81.             s = run.query(sql, new ScalarHandler(1), params);  
  82.         } catch (SQLException e) {  
  83.             e.printStackTrace();  
  84.         }  
  85.         return s;  
  86.     }  
  87.   
  88.     /** 
  89.      * 查询返回单个对象 
  90.      *  
  91.      * @param sql 
  92.      * @param clazz 
  93.      * @return 
  94.      */  
  95.     public  T queryForObject(String sql, Object param[], Class clazz) {  
  96.         T obj = null;  
  97.         try {  
  98.             showSql(sql);  
  99.             obj = (T) run.query(sql, new BeanHandler(clazz), param);  
  100.         } catch (SQLException e) {  
  101.             e.printStackTrace();  
  102.         }  
  103.         return obj;  
  104.     }  
  105.   
  106.     /** 
  107.      * 查询返回list对象 
  108.      *  
  109.      * @param sql 
  110.      * @param clazz 
  111.      * @return 
  112.      */  
  113.     public  List queryForOList(String sql, Object[] param, Class clazz) {  
  114.         List obj = null;  
  115.         try {  
  116.             showSql(sql);  
  117.             obj = (List) run.query(sql, new BeanListHandler(clazz), param);  
  118.         } catch (SQLException e) {  
  119.             e.printStackTrace();  
  120.         }  
  121.         return obj;  
  122.     }  
  123.   
  124.     /** 
  125.      * 保存返回主键 
  126.      *  
  127.      * @param sql 
  128.      * @param param 
  129.      * @return 
  130.      */  
  131.     public int storeInfoAndGetGeneratedKey(String sql, Object[] param) {  
  132.         int pk = 0;  
  133.         try {  
  134.             showSql(sql);  
  135.             run.update(sql, param);  
  136.             pk = ((Long) run.query("SELECT LAST_INSERT_ID()"new ScalarHandler(1))).intValue();  
  137.         } catch (SQLException e) {  
  138.             e.printStackTrace();  
  139.         }  
  140.         return pk;  
  141.     }  
  142.   
  143.     /** 
  144.      * 更新 
  145.      *  
  146.      * @param sql 
  147.      * @return 
  148.      */  
  149.   
  150.     public int update(String sql, Object[] param) {  
  151.         int i = 0;  
  152.         try {  
  153.             showSql(sql);  
  154.             i = run.update(sql, param);  
  155.         } catch (SQLException e) {  
  156.             e.printStackTrace();  
  157.         }  
  158.         return i;  
  159.   
  160.     }  
  161.   
  162.     private void showSql(String sql) {  
  163.         System.out.println(sql);  
  164.     }  
  165.   
  166.     public static void main(String[] args) {  
  167.         DataSource ds = setupDataSource();  
  168.         DBBase db = new DBBase();  
  169.         db.setDataSource(ds);  
  170.         db.init();  
  171.   
  172.         // 聚合函数查询结果  
  173.         String sql = "select count(*) from IceRecord";  
  174.         int result1 = db.count(sql, null);  
  175.         System.out.println("聚合函数查询结果:" + result1);  
  176.   
  177.         // 通过List封装  
  178.         sql = "select * from IceRecord";  
  179.         List vars = DBBase.getInstance().queryForOList(sql, null, Var.class);  
  180.         for (Var var : vars) {  
  181.             System.out.println("通过List封装:" + var.getId() + " " + var.getValue_t() + " " + var.getDate_Time());  
  182.         }  
  183.   
  184.         // 插入数据  
  185.         sql = "insert into IceRecord(value_t) values(?)";  
  186.         int pk = DBBase.getInstance().storeInfoAndGetGeneratedKey(sql, new Object[] { 1 });  
  187.         System.out.println("/插入数据:" + pk);  
  188.   
  189.         // 按条件查询数据  
  190.         sql = "select Date_Time from IceRecord where id =?";  
  191.         String result2 = (String) DBBase.getInstance().getAnAttr(sql, new Object[] { 1 });  
  192.         System.out.println("按条件查询数据:" + result2);  
  193.   
  194.     }  
  195.   
  196.     // 初始化数据源  
  197.     private static DataSource setupDataSource() {  
  198.         BasicDataSource ds = new BasicDataSource();  
  199.         ds.setDriverClassName("com.mysql.jdbc.Driver");  
  200.         ds.setUsername("root");  
  201.         ds.setPassword("147258369");  
  202.         ds.setUrl("jdbc:mysql://127.0.0.1:3306/test");  
  203.         return ds;  
  204.     }  
  205. /* 
  206. 运行结果: 
  207. select count(*) from IceRecord 
  208. 聚合函数查询结果:7 
  209. select * from IceRecord 
  210. 通过List封装:1 100.0 2010-07-31 
  211. 通过List封装:2 200.0 2010-07-30 
  212. 通过List封装:3 300.0 2010-07-29 
  213. 通过List封装:4 400.0 2010-07-28 
  214. 通过List封装:5 500.0 2010-07-27 
  215. 通过List封装:6 600.0 2010-07-26 
  216. 通过List封装:7 1.0  
  217. insert into IceRecord(value_t) values(?) 
  218. /插入数据:8 
  219. select Date_Time from IceRecord where id =? 
  220. 按条件查询数据:2010-07-31 
  221. */  
  222.   
  223. }  






Java代码  收藏代码
  1. package test.common.db;  
  2.   
  3. public class Var {  
  4.     private int id;  
  5.     private float value_t;  
  6.     private String Date_Time;  
  7.   
  8.     public int getId() {  
  9.         return id;  
  10.     }  
  11.   
  12.     public void setId(int id) {  
  13.         this.id = id;  
  14.     }  
  15.   
  16.     public float getValue_t() {  
  17.         return value_t;  
  18.     }  
  19.   
  20.     public void setValue_t(float valueT) {  
  21.         value_t = valueT;  
  22.     }  
  23.   
  24.     public String getDate_Time() {  
  25.         return Date_Time;  
  26.     }  
  27.   
  28.     public void setDate_Time(String dateTime) {  
  29.         Date_Time = dateTime;  
  30.     }  
  31. }  




     总结,这是一个轻量级架构,功能肯定没有JPA和Hibernate强大,仅适用于JDBC编写的应用.同时他更重要的意义是规范.请读者们根据具体项目,选择最适合项目框架进行应用.而不要生搬硬套本代码到那些不适合commons-dbutils的项目中.^-^

抱歉!评论已关闭.