使用dbutils进行数据库操作

  Common Dbutils是操作数据库的组件,是一个开源的JDBC工具类库,对传统操作数据库的类进行二次封装,可以把结果集转化成List。

  DBUtils是java编程中的数据库操作实用工具,小巧简单实用,没有Hibernate等一些ORM框架的庞大,繁琐的配置。
  1.对于数据表的读操作,他可以把结果转换成List,Array,Set等java集合,便于程序员操作;
  2.对于数据表的写操作,也变得很简单(只需写sql语句)
  3.可以使用数据源,使用JNDI,数据库连接池等技术来优化性能--重用已经构建好的数据库连接对象,而不像php,asp那样,费时费力的不断重复的构建和析构这样的对象。
  但是,如果使用dbutils包的话,需要注意以下几点:
  1.实体类属性的名称要与库中字段的名字一致,否则无法查到结果。
  2.ResultSetHandler rsh = 接口的实现类
    如果返回对象的话使用new BeanHandler();
    如果返回的是集合的话使用 new BeanListHandler();
  3.等等可以参考官方文档或其他资料

调用主要类

  • org.apache.commons.dbutils.QueryRunner
  • org.apache.commons.dbutils.ResultSetHandler
  • org.apache.commons.dbutils.DbUtils

Dbutils用法

  dbutils封装了jdbc的增删改查的操作,只需要new一个QueryRunner,然后调用其query方法,将sql语句,参数或参数数组,传入结果集处理器递。
结果集处理器ResultSetHandler 接口的实现类 

  1. ArrayHandler:把结果集中的第一行数据转成对象数组。
  2. ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
  3. BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
  4. BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
  5. ColumnListHandler:将结果集中某一列的数据存放到List中。
  6. KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
  7. MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
  8. MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List

  在mvc模式中,dao层只负责对数据库的操作,不应该有任何业务逻辑的代码,但是有一种情况,比如银行转账,几次数据库操作在一次事务中,在service中如何将转账服务放在一次事务中呢,一种解决办法是在dao层中保存一个Connection,由service传递进来对那个Connection操作,就可以解决这个问题。
  在mvc模式下,如何进行事务管理呢,上面的方法是,所有的dao层共享同一事务,即同一连接,实现此需求的另外一种方法是使用ThreadLocale技术,这个对象保存的是一个线程为键的map,如果在dao层中将得到的Connection存放在这个map中,则在service中得到的连接就是同一连接,可以写一个工具类实现获取连接,提交,回滚,关闭等操作。
  以上两种方法只能在dao层中实现共享事务,但是如果是servlet转发等情况,便不是同一连接,这时候就必须将事务管理提前到servlet之前,就写一个拦截器,每一次请求都获取连接,然后放行给servlet等,返回时再关闭连接等,缺点是占用连接时间过长,所以使用spring是好的方法,但是比较臃肿。

下面例子是dbutils+反射对Dao简单使用

实体类 UserRoleVo.java

public class UserRoleVo {
    int id;
    String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "UserRoleVo [id=" + id + ", name=" + name + "]";
    }
}

 

基于泛型的BaseDao.java

import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;


import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

public class BaseDao<T> {
    private static final String CLASSNAME="com.microsoft.sqlserver.jdbc.SQLServerDriver";
    private static final String URL="jdbc:sqlserver://127.0.0.1:1433;databasename=MybookShop";
    private static final String UID="sa";
    private static final String PWD="";
    
    private Class cls;
    public Connection getConn() throws SQLException {
        Connection conn=DriverManager.getConnection(URL,UID,PWD);
        return conn;
    }

    public DBM() throws SQLException{
        DbUtils.loadDriver(CLASSNAME);
        
        cls= (Class)((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        
    }
    public List<T> query(String sql,Object...paras) throws SQLException{
        QueryRunner qr=new QueryRunner();
        BeanListHandler handler=new BeanListHandler(cls);
        Connection conn=getConn();
        List<T> list= (List<T>) qr.query(getConn(), sql,paras , handler);
        DbUtils.close(conn);
        return list;
    }
    
    public void update(String sql,Object...paras) throws SQLException{
        QueryRunner qr=new QueryRunner();
        Connection conn=getConn();
        qr.update(conn, sql,paras);
        DbUtils.close(conn);
    }
    
    
}

 

数据访问层类UserRoleDAO.java:

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;



import com.accp.db.DBM;
import com.accp.vo.UserRoleVo;

public class UserRoleDao extends BaseDao<UserRoleVo> {
    public UserRoleDao() throws SQLException {
        super();        
    }

    public List<UserRoleVo> findAll() throws SQLException{
        return query("select * from userRoles");
    }
    
    public List<UserRoleVo> findAllByName(String name) throws SQLException{
        return query( "select * from userRoles where name like ?","%"+name+"%");
    }
    
    public void add(UserRoleVo role) throws SQLException{
        update("insert into userRoles values (?)",role.getName());
    }
}

  这样的BaseDao就可以很方便地被子类继承使用query(),update()等方法,没有set(),get()繁琐过程就可以得到结果集。其实还可以继续封装像http://www.oschina.net/code/snippet_12_2746(不过POJO是Bean 类的基类,这样做法好像代码不清晰)但你还是可以用其他办法想上面的例子一样封装操作数据库方法,只不过需要稍稍修改,如

/**
     * 分页列出所有对象
     * @param page
     * @param size
     * @return
     */
    public List<? extends POJO> List(int page, int size) {
        String sql = "SELECT * FROM " + TableName() + " ORDER BY id DESC";
        return QueryHelper.query_slice(getClass(), sql, page, size);
    }
    
    public List<? extends POJO> Filter(String filter, int page, int size) {
        String sql = "SELECT * FROM " + TableName() + " WHERE " + filter + " ORDER BY id DESC";
        return QueryHelper.query_slice(getClass(), sql, page, size);
    }
/**
     * 根据主键读取对象详细资料,根据预设方法自动判别是否需要缓存
     * @param id
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T extends POJO> T Get(long id) {
        if(id <= 0) return null;
        String sql = "SELECT * FROM " + TableName() + " WHERE id=?";
        boolean cached = IsObjectCachedByID();
        return (T)QueryHelper.read_cache(getClass(), cached?CacheRegion():null, id, sql, id);
    }
    
    public List<? extends POJO> BatchGet(List<Long> ids) {
        if(ids==null || ids.size()==0)
            return null;
        StringBuilder sql = new StringBuilder("SELECT * FROM " + TableName() + " WHERE id IN (");
        for(int i=1;i<=ids.size();i++) {
            sql.append('?');
            if(i < ids.size())
                sql.append(',');
        }
        sql.append(')');
        List<? extends POJO> beans = QueryHelper.query(getClass(), sql.toString(), ids.toArray(new Object[ids.size()]));
        if(IsObjectCachedByID()){
            for(Object bean : beans){
                CacheManager.set(CacheRegion(), ((POJO)bean).getId(), (Serializable)bean);
            }
        }
        return beans;
    }
/**
     * 插入对象
     * @param obj
     * @return 返回插入对象的主键
     */
    
    private static long _InsertObject(POJO obj) {        
        Map<String, Object> pojo_bean = obj.ListInsertableFields();        
        String[] fields = pojo_bean.keySet().toArray(new String[pojo_bean.size()]);
        StringBuilder sql = new StringBuilder("INSERT INTO ") ;
        sql.append(obj.TableName());
        sql.append('(');
        for(int i=0;i<fields.length;i++){
            if(i > 0) sql.append(',');
            sql.append(fields[i]);
        }
        sql.append(") VALUES(");
        for(int i=0;i<fields.length;i++){
            if(i > 0) sql.append(',');
            sql.append('?');
        }
        sql.append(')');
        PreparedStatement ps = null;
        ResultSet rs = null;
        try{
            ps = QueryHelper.getConnection().prepareStatement(sql.toString(), PreparedStatement.RETURN_GENERATED_KEYS);        
            for(int i=0;i<fields.length;i++){
                ps.setObject(i+1, pojo_bean.get(fields[i]));
            }
            ps.executeUpdate();
            rs = ps.getGeneratedKeys();
            return rs.next()?rs.getLong(1):-1;
        }catch(SQLException e){
            throw new DBException(e);
        }finally{
            DbUtils.closeQuietly(rs);
            DbUtils.closeQuietly(ps);
            sql = null;
            fields = null;
            pojo_bean = null;
        }
    }

这样的话数据层的子类会更加简单,大大减少代码量。

最后我是想说不用Hibernate等一些ORM框架,是感觉用了之后不灵活。

 

posted on 2012-08-27 17:45  刀光建影  阅读(2801)  评论(0编辑  收藏  举报

导航