Apache Commons DbUtils整合Spring框架實現簡單的CRUD

Commons DbUtils是Apache提供的一個對JDBC進行簡單封裝的開源工具類庫,可以簡化JDBC相關的開發。Commons DbUtils能夠很是方便的整合Spring Framework,比較輕量級,執行SQL語句很是方便(特別是查詢語句),能夠代替Spring JdbcTemplate、MyBatis等數據庫訪問層技術。java

配置

DbUtils經過QueryRunner類來執行SQL,使用起來很是相似於Spring框架中的JdbcTemplatemysql

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test_db" />
    <property name="username" value="root" />
    <property name="password" value="xxx" />
</bean>
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
    <constructor-arg ref="dataSource" />
</bean>

我這裏使用的鏈接池是HikariCP,這裏能夠根據須要換成其餘的鏈接池,例如DBCP、Druid等。spring

因爲DbUtils自己不支持Spring事務,若是想要支持事務,例如@Transactional註解,還須要給DataSource加一層代理:sql

<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
    <property name="targetDataSource">
        <bean class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test_db" />
            <property name="username" value="root" />
            <property name="password" value="xxx" />
        </bean>
    </property>
</bean>
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
    <constructor-arg ref="dataSource" />
</bean>

Java代碼中能夠經過Autowired引入QueryRunner:數據庫

public class UserDao {

    @Autowired
    private QueryRunner queryRunner;
}

增刪改

增刪改操做,也就是INSERT、DELETE、UPDATE語句,均可以經過QueryRunner的execute方法來直接執行:apache

queryRunner.execute("delete from user_info");
queryRunner.execute("update user_info set user_name=?,user_age=? where user_id=?", "xxg", 28, 6);

因爲DbUtils自己也是基於JDBC中的PreparedStatement來實現的,因此也是支持SQL中帶有參數的。app

查詢

ResultSetHandler

ResultSetHandler是DbUtils中的一個接口,該接口的實現類可用於將JDBC查詢語句返回的結果(也就是ResultSet),轉成你想要的數據類型。這個和Spring JdbcTemplate查詢時用到的RowMapper接口很是相似。框架

下面寫了一個ResultSetHandler實現類,將一條SQL的查詢結果轉爲一個List<User>:ide

List<User> list = queryRunner.query("select * from user_info limit 100", new ResultSetHandler<List<User>>() {
    @Override
    public List<User> handle(ResultSet rs) throws SQLException {
        List<User> l = new ArrayList<User>();
        while (rs.next()) {
            User user = new User();
            user.setUserId(rs.getInt("user_id"));
            user.setUserName(rs.getString("user_name"));
            user.setCreateTime(rs.getTimestamp("create_time"));
            l.add(user);
        }
        return l;
    }
});

因爲ResultSetHandler接口中只有一個抽象方法,因此若是是Java 8版本的話也可使用Lambda表達式來簡化代碼:工具

List<User> list = queryRunner.query("select * from user_info limit 100", rs -> {
    List<User> l = new ArrayList<User>();
    while (rs.next()) {
        User user = new User();
        user.setUserId(rs.getInt("user_id"));
        user.setUserName(rs.getString("user_name"));
        user.setCreateTime(rs.getTimestamp("create_time"));
        l.add(user);
    }
    return l;
});

經常使用ResultSetHandler實現類

DbUtils提供了一些經常使用的ResultSetHandler實現類,能夠簡化查詢,通常狀況下不須要像上面那樣本身來實現ResultSetHandler接口。

ScalarHandler

用於返回查詢結果第一行第一列數據:

long count = queryRunner.query("select count(*) from user_info", new ScalarHandler<Long>()); // 查詢count
String userName = queryRunner.query("select user_name from user_info where user_id=?", new ScalarHandler<String>(), 1); // 查詢user_id=1的用戶的用戶名

ColumnListHandler

返回查詢結果(全部行)第一列的數據List:

List<String> userNameList = queryRunner.query("select user_name from user_info", new ColumnListHandler<String>()); // 查詢全部用戶的user_name

MapHandler

返回查詢結果第一行數據(全部列)並組裝成Map,Map的key爲列名,value爲值:

Map<String, Object> userInfo = queryRunner.query("select user_id,user_name from user_info where user_id=1", new MapHandler());
long userId = (Long) userInfo.get("user_id");
String userName = (String) userInfo.get("user_name");

MapListHandler

MapHandler機制相似,MapListHandler會將ResultSet轉成一個List<Map<String, Object>>

List<Map<String, Object>> dataList = queryRunner.query("select user_id,user_name from user_info", new MapListHandler());

ArrayHandler

返回查詢結果第一行數據,將全部列值按順序組成一個數據:

Object[] data = queryRunner.query("select user_id,user_name from user_info where user_id=1", new ArrayHandler());
long userId = (Long) data[0];
String userName = (String) data[1];

ArrayListHandler

ArrayHandler機制相似,ArrayListHandler會將ResultSet轉成一個List<Object[]>

List<Object[]> list = queryRunner.query("select user_id,user_name from user_info", new ArrayListHandler());

KeyedHandler

將ResultSet轉爲Map<?, Map<String, Object>>,外層Map每一個元素對應查詢結果的一條數據,key爲數據的主鍵或者惟一索引,value也是一個Map,內容是一行數據的列名和值,和MapHandler機制相似:

Map<Long, Map<String, Object>> dataMap = queryRunner.query("select user_id,user_name from user_info", new KeyedHandler<Long>("user_id")); // Key指定爲user_id列
Map<String, Object> data = dataMap.get(1L); // 獲取user_id=1的一條記錄
long userId = (Long) data.get("user_id");
String userName = (String) data.get("user_name");

BeanHandler

BeanHandler是比較實用的一個類,能夠經過反射機制將查詢結果第一行數據根據數據庫列名映射到Java對象上,先定義一個Java對象:

public class User {

    private int userId;
    private String userName;
    private int userAge;
    private Date createTime;

    // 省略getter setter
}

執行查詢:

// 查詢user_id=1的用戶數據並返回User對象
User user = queryRunner.query("select user_id as userId,user_name as userName,user_age as userAge,create_time as createTime from user_info where user_id=1", new BeanHandler<User>(User.class));

數據庫列名不少人會使用下劃線做爲單詞間分隔符,而Java命名規範要求變量名是駝峯命名,這樣會致使沒法直接映射,因此上面代碼中在SQL語句上經過AS將列名下劃線分隔符轉成駝峯命名。可是若是字段比較多,或者想使用select *查詢,上面的這種方法就很差使了。下面提供一種方案,能夠將帶有下劃線分隔符的列名映射到駝峯命名的Java對象上:

User user = queryRunner.query("select user_id,user_name,user_age,create_time from user_info where user_id=1",
        new BeanHandler<User>(User.class, new BasicRowProcessor(new GenerousBeanProcessor())));

BeanListHandler

BeanHandler機制相似,BeanListHandler能夠將多條查詢結果轉爲Java Bean的List:

List<User> userList = queryRunner.query("select user_id as userId,user_name as userName,user_age as userAge,create_time as createTime from user_info",
        new BeanListHandler<User>(User.class));

一樣也能夠將帶有下劃線分隔符的列名映射到駝峯命名的Java對象上:

List<User> userList = queryRunner.query("select user_id,user_name,user_age,create_time from user_info",
        new BeanListHandler<User>(User.class, new BasicRowProcessor(new GenerousBeanProcessor())));

BeanMapHandler

相似於KeyedHandler機制,將ResultSet轉爲一個Map,Map中每條數據對應查詢結果的一條數據,key爲數據的主鍵或者惟一索引,value是數據經過反射機制轉成的Java對象:

Map<Long, User> users = queryRunner.query("select user_id as userId,user_name as userName,user_age as userAge,create_time as createTime from user_info",
        new BeanMapHandler<Long, User>(User.class, "userId")); // 使用userId列做爲Map的key
User user1 = users.get(1L); // 獲取user_id=1的用戶

一樣也能夠將帶有下劃線分隔符的列名映射到駝峯命名的Java對象上:

// Map的key默認使用查詢語句中的第一列(即主鍵user_id)
Map<Long, User> users = queryRunner.query("select user_id,user_name,user_age,create_time from user_info",
        new BeanMapHandler<Long, User>(User.class, new BasicRowProcessor(new GenerousBeanProcessor())));
User user1 = users.get(1L); // 獲取user_id=1的用戶

關注我

2029039401-5cbbeaa85763a_articlex.jpeg

相關文章
相關標籤/搜索