commons-dbutils是Apache組織提供的一個開源JDBC工具類庫,它是對JDBC的簡單封裝,學習成本極低,而且使用dbutils能極大簡化jdbc編碼的工做量,同時也不會影響程序的性能。所以dbutils成爲不少不喜歡hibernate的公司的首選。 dbutils的官方網站http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgiphp
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
該接口用於處理java.sql.ResultSet,將數據按要求轉換爲另外一種形式。ResultSetHandler接口提供了一個單獨的方法:Object handle (java.sql.ResultSet .rs)
。api
ResultSetHandler接口的實現類數組
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以前,咱們先編寫測試用的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聽從如下步驟
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; }
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; }
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是一個開源的JDBC鏈接池,它實現了數據源和JNDI綁定,支持JDBC3規範和JDBC2的標準擴展。目前使用它的開源項目有Hibernate,Spring等
數據庫鏈接池負責分配、管理和釋放數據庫鏈接,它容許應用程序重複使用一個現有的數據庫鏈接,而不是再從新創建一個;鏈接池容許多個客戶端使用緩存起來的鏈接對象,這些對象能夠鏈接數據庫,它們是共享的、可被重複使用的。
打開/關閉數據庫鏈接開銷很大,鏈接池技術容許咱們在鏈接池裏維護鏈接對象,這樣能夠提升數據庫的執行命令的性能。多個客戶端請求能夠重複使用相同的鏈接對象,當每次收到一個客戶端請求時,就會搜索鏈接池,看看有沒有閒置的鏈接對象。若是沒有閒置對象的話,要麼全部的客戶端請求都進入隊列排隊,要麼在池中建立一個新的鏈接對象(這取決於池裏已經有多少個鏈接存在以及配置支持多少鏈接)。一旦某個請求使用完鏈接對象以後,這個對象會被從新放入池中,而後會被從新分派給排隊等待的請求(分派給哪一個請求要看使用什麼調度算法)。由於大部分請求都是使用現存的鏈接對象,因此鏈接池技術大大減小了等待建立數據庫鏈接的時間,從而減小了平均鏈接時間。
因爲數據庫鏈接得以重用,避免了頻繁建立,釋放鏈接引發的大量性能開銷。在減小系統消耗的基礎上,另外一方面也增長了系統運行環境的平穩性。
數據庫鏈接池在初始化過程當中,每每已經建立了若干數據庫鏈接置於鏈接池中備用。此時鏈接的初始化工做均已完成。對於業務請求處理而言,直接利用現有可用鏈接,避免了數據庫鏈接初始化和釋放過程的時間開銷,從而減小了系統的響應時間。
在較爲完善的數據庫鏈接池實現中,可根據預先的佔用超時設定,強制回收被佔用鏈接,從而避免了常規數據庫鏈接操做中可能出現的資源泄露。
在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>
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; } }
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; }
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; }