DBUtils 學習使用

DBUtils 學習使用

commons-dbutils簡介

commons-dbutils是Apache組織提供的一個開源JDBC工具類庫,它是對JDBC的簡單封裝,學習成本極低,而且使用dbutils能極大簡化jdbc編碼的工做量,同時也不會影響程序的性能。所以dbutils成爲不少不喜歡hibernate的公司的首選。 dbutils的官方網站http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgiphp

image

dbutils 優勢

  1. 對於數據表的讀操做,他能夠把結果轉換成List,Array,Set等java集合,便於程序員操做;
  2. 對於數據表的寫操做,也變得很簡單(只需寫sql語句)
  3. 可使用數據源,使用JNDI,數據庫鏈接池(dbcp,c3p0)等技術來優化性能--重用已經構建好的數據庫鏈接對象,而不像php,asp那樣,費時費力的不斷重複的構建和析構這樣的對象。

commons-dbutils API介紹

  • org.apache.commons.dbutils.QueryRunner QueryRunner (insert、update、delete使用)
  • org.apache.commons.dbutils.ResultSetHandler (用於查詢結果處理使用)
  • org.apache.commons.dbutils.DbUtils (工具類)

QueryRunner 類的主要方法

  • public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException

執行一個查詢操做,在這個查詢中,對象數組中的每一個元素值被用來做爲查詢語句的置換參數。該方法會自行處理PreparedStatement和ResultSet的建立和關閉。java

  • public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException

幾乎與第一種方法同樣;惟一的不一樣在於它不將數據庫鏈接提供給方法,而且它是從提供給構造方法的數據源(DataSource)或使用的setDataSource方法中從新得到Connection。mysql

  • public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException

執行一個不須要置換參數的查詢操做。程序員

  • public int update(Connection conn, String sql, Object[] params) throws SQLException

用來執行一個更新(插入、更新或刪除)操做。算法

  • public int update(Connection conn, String sql) throws SQLException

用來執行一個不須要置換參數的更新操做。sql

  • public int[] batch(Connection conn, String sql, Object[][] params) throws SQLException

這個方法對應着批處理,常常用於在同一個表中批量插入數據,或批量更新表的數據。 該方法爲什麼會接收二維數組Object[][] params呢? 答:例如如今要想在同一個表中批量插入數據,編寫的SQL語句爲:數據庫

String sql = "insert into users(id,name) values(?,?)"; 

該方法接收二維數組Object[][] params,那麼調用其的時候就要傳遞一個諸如這樣的實參[[1,aa],[2,bb],[3,cc]],即用二維數組裏面的每個一維數組生成一條sql語句。 那爲什麼又會返回int[]呢? 答:該方法的返回值是int[],因此會返回諸如這樣的結果:[1,1,1],意思是生成的第一條sql語句影響數據庫幾行、生成的第二條sql語句影響數據庫幾行、生成的第三條sql語句影響數據庫幾行。apache

ResultSetHandler接口使用講解

該接口用於處理java.sql.ResultSet,將數據按要求轉換爲另外一種形式。ResultSetHandler接口提供了一個單獨的方法:Object handle (java.sql.ResultSet .rs)api

ResultSetHandler接口的實現類數組

  • ArrayHandler:把結果集中的第一行數據轉成對象數組。
  • ArrayListHandler:把結果集中的每一行數據都轉成一個數組,再存放到List中。
  • BeanHandler:將結果集中的第一行數據封裝到一個對應的JavaBean實例中。
  • BeanListHandler:將結果集中的每一行數據都封裝到一個對應的JavaBean實例中,存放到List裏。
  • ColumnListHandler:將結果集中某一列的數據存放到List中。
  • KeyedHandler(name):將結果集中的每一行數據都封裝到一個Map裏,再把這些map再存到一個map裏,其key爲指定的key。
  • MapHandler:將結果集中的第一行數據封裝到一個Map裏,key是列名,value就是對應的值。
  • MapListHandler:將結果集中的每一行數據都封裝到一個Map裏,而後再存放到List。

DbUtils類使用講解

DbUtils:提供如關閉鏈接、裝載JDBC驅動程序等常規工做的工具類,裏面的全部方法都是靜態的。主要方法以下:

  • public static void close(…) throws java.sql.SQLException DbUtils類提供了三個重載的關閉方法。這些方法檢查所提供的參數是否是NULL,若是不是的話,它們就關閉Connection、Statement和ResultSet。
  • public static void closeQuietly(…) 這一類方法不只能在Connection、Statement和ResultSet爲NULL狀況下避免關閉,還能隱藏一些在程序中拋出的SQLException。
  • public static void commitAndCloseQuietly(Connection conn) 用來提交鏈接,而後關閉鏈接,而且在關閉鏈接時不拋出SQL異常。
  • public static boolean loadDriver(java.lang.String driverClassName) 這一方法裝載並註冊JDBC驅動程序,若是成功就返回true。使用該方法,你不須要捕捉這個異常ClassNotFoundException。

使用DBUtils完成數據庫的CRUD

在使用DBUtils完成數據庫的CRUD以前,咱們先編寫測試用的SQL腳本:

CREATE TABLE `user` ( `id` int(11) NOT NULL auto_increment, `name` varchar(50) NOT NULL, `age` tinyint(10) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 

使用dbutils聽從如下步驟

  1. 加載JDBC驅動程序類,並用DriverManager來獲得一個數據庫鏈接conn。
  2. 實例化 QueryRunner,獲得實例化對象qRunner。
  3. qRunner.update()方法,執行增改刪的sql命令,qRunner.query()方法,獲得結果集。

獲取鏈接對象

private static final String url = "jdbc:mysql://192.168.1.15:3306/test?useUnicode=true&characterEncoding=utf8"; private static final String driver = "com.mysql.jdbc.Driver"; private static final String user = "znsd_test"; private static final String password = "123456"; public static Connection getConnect() { Connection conn = null; try { Class.forName(driver); conn = DriverManager.getConnection(url, user, password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return conn; } 

建立bean對象關聯數據庫

public class User implements Serializable { private Integer id; // 用戶ID private String name; // 用戶姓名 private Integer age; // 用戶年齡 // ...忽略set、get方法 } 

添加

public Integer add(User user) { QueryRunner queryRunner = new QueryRunner(); Connection connect = ConnectionUtil.getConnect(); try { return queryRunner.update(connect, "insert into user(name, age) values(?, ?)", user.getName(), user.getAge()); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(connect); } return 0; } 

修改

public Integer update(User user) { QueryRunner queryRunner = new QueryRunner(); Connection conn = ConnectionUtil.getConnect(); try { return queryRunner.update(conn , "update user set name = ?, age = ? where id = ?", user.getName(), user.getAge(), user.getId()); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(conn); } return 0; } 

刪除

public Integer delete(Integer id) { QueryRunner queryRunner = new QueryRunner(); Connection conn = ConnectionUtil.getConnect(); try { return queryRunner.update(conn , "delete from user where id = ?", id); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(conn); } return 0; } 

批量添加

public int[] batch(Object[][] values) { QueryRunner queryRunner = new QueryRunner(); Connection conn = ConnectionUtil.getConnect(); try { return queryRunner.batch(conn, "insert into user(name, age) values(?, ?)", values); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(conn); } return null; } 

查詢全部

public List<User> select() { QueryRunner queryRunner = new QueryRunner(); Connection conn = ConnectionUtil.getConnect(); try { return queryRunner.query(conn, "select id id1, name, age from user", new UserBeanListHandler(User.class)); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(conn); } return null; } 

查詢返回map

public List<Map<String, Object>> selectAsMap() { QueryRunner queryRunner = new QueryRunner(); Connection conn = ConnectionUtil.getConnect(); try { List<Map<String, Object>> userMaps = queryRunner.query(conn, "select id id1, name, age from user", new MapListHandler()); return userMaps; } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(conn); } return null; } 

查詢單個對象

public User selectOne(Integer id) { QueryRunner queryRunner = new QueryRunner(); Connection conn = ConnectionUtil.getConnect(); try { return queryRunner.query(conn, "select id id1, name, age from user where id = ? limit 1", new BeanHandler<User>(User.class) { @Override public User handle(ResultSet rs) throws SQLException { if (rs.next()) { return new User(rs.getInt("id1"), rs.getString("name"), rs.getInt("age")); } return null; } }, id); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(conn); } return null; } 

結合c3p0數據源使用dbutils

c3p0簡介

C3P0是一個開源的JDBC鏈接池,它實現了數據源和JNDI綁定,支持JDBC3規範和JDBC2的標準擴展。目前使用它的開源項目有Hibernate,Spring等

數據庫鏈接池簡介

數據庫鏈接池負責分配、管理和釋放數據庫鏈接,它容許應用程序重複使用一個現有的數據庫鏈接,而不是再從新創建一個;鏈接池容許多個客戶端使用緩存起來的鏈接對象,這些對象能夠鏈接數據庫,它們是共享的、可被重複使用的。

打開/關閉數據庫鏈接開銷很大,鏈接池技術容許咱們在鏈接池裏維護鏈接對象,這樣能夠提升數據庫的執行命令的性能。多個客戶端請求能夠重複使用相同的鏈接對象,當每次收到一個客戶端請求時,就會搜索鏈接池,看看有沒有閒置的鏈接對象。若是沒有閒置對象的話,要麼全部的客戶端請求都進入隊列排隊,要麼在池中建立一個新的鏈接對象(這取決於池裏已經有多少個鏈接存在以及配置支持多少鏈接)。一旦某個請求使用完鏈接對象以後,這個對象會被從新放入池中,而後會被從新分派給排隊等待的請求(分派給哪一個請求要看使用什麼調度算法)。由於大部分請求都是使用現存的鏈接對象,因此鏈接池技術大大減小了等待建立數據庫鏈接的時間,從而減小了平均鏈接時間。

20171021162546066

使用鏈接池的優勢

  • 資源重用:

因爲數據庫鏈接得以重用,避免了頻繁建立,釋放鏈接引發的大量性能開銷。在減小系統消耗的基礎上,另外一方面也增長了系統運行環境的平穩性。

  • 更快的系統反應速度:

數據庫鏈接池在初始化過程當中,每每已經建立了若干數據庫鏈接置於鏈接池中備用。此時鏈接的初始化工做均已完成。對於業務請求處理而言,直接利用現有可用鏈接,避免了數據庫鏈接初始化和釋放過程的時間開銷,從而減小了系統的響應時間。

  • 統一的鏈接管理,避免數據庫鏈接泄露:

在較爲完善的數據庫鏈接池實現中,可根據預先的佔用超時設定,強制回收被佔用鏈接,從而避免了常規數據庫鏈接操做中可能出現的資源泄露。

使用步驟

  1. 首先要導入c3p0和dbutils以及mysql的jar包
  • c3p0-0.9.5.2.jar
  • commons-dbutils-1.7.jar
  • mchange-commons-java-0.2.11.jar
  • mysql-connector-java-5.1.22.jar
  1. 編寫c3p0的配置文件c3p0-config.xml

在src目錄下存放c3p0的配置文件,配置文件是c3p0本身去識別並讀入的,咱們不須要在代碼中作任何的操做,可是配置文件必定要命名爲c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- 這是默認配置信息 --> <default-config> <!-- jdbc鏈接四大參數配置 --> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://192.168.1.15:3306/test</property> <property name="user">znsd_test</property> <property name="password">123456</property> <!-- 池參數配置 --> <!--JDBC的標準參數,用以控制數據源內加載的PreparedStatements數量。但因爲預緩存的statements 屬於單個connection而不是整個鏈接池。因此設置這個參數須要考慮到多方面的因素。 若是maxStatements與maxStatementsPerConnection均爲0,則緩存被關閉。Default: 0 --> <property name="acquireIncrement">3</property> <!--初始化時獲取的鏈接數,取值應在minPoolSize與maxPoolSize之間。Default: 3 --> <property name="initialPoolSize">10</property> <!--鏈接池中保留的最小鏈接數。--> <property name="minPoolSize">2</property> <!--鏈接池中保留的最大鏈接數。Default: 15 --> <property name="maxPoolSize">10</property> </default-config> </c3p0-config> 
  1. 使用c3p0獲取獲取數據庫鏈接對象
public class C3p0ConnectionUtil { // 配置文件的默認配置!要求你必須給出c3p0-config.xml private static ComboPooledDataSource c3p0DataSource = new ComboPooledDataSource(); /** * 獲取鏈接對象 * @return */ public static Connection getConnection() { try { // 獲得鏈接器 return c3p0DataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return null; } /** * 獲取數據源 * * @return */ public static DataSource getDataSource() { return c3p0DataSource; } } 
  1. dbutils 使用c3p0
public Integer add(User user) { QueryRunner queryRunner = new QueryRunner(C3p0ConnectionUtil.getDataSource()); try { return queryRunner.update("insert into user(name, age) values(?, ?)", user.getName(), user.getAge()); } catch (SQLException e) { e.printStackTrace(); } return 0; } 
  1. 返回主鍵例子
public Integer add(User user) { DataSource dataSource = C3p0ConnectionUtil.getDataSource(); QueryRunner queryRunner = new QueryRunner(dataSource); try { String sql = "insert into user(name, age) values(?, ?)"; // 須要條用insert方法,指定MapHandler參數 Map<String, Object> idMap = queryRunner.insert(sql, new MapHandler() { @Override public Map<String, Object> handle(ResultSet rs) throws SQLException { //rs = rs.getStatement().getGeneratedKeys(); // 獲取主鍵 int id = rs.next() ? rs.getInt(1) : -1; // 將數據庫返回主鍵放入map中 Map<String, Object> idMap = new HashMap<String, Object>(); idMap.put("id", id); return idMap; } }, user.getName(), user.getAge()); return (Integer) idMap.get("id"); } catch (SQLException e) { e.printStackTrace(); } return 0; }
相關文章
相關標籤/搜索