簡明入門教程,參考:https://www.cnblogs.com/CQY1183344265/p/5854418.html
進行此章節之前,介紹一個JdbcUtils的再次的簡單封裝
(例如后面需要構造QueryRunner時得到數據源等的簡便的操作)
package cn.itcast.jdbcutils;import java.sql.Connection;
import java.sql.SQLException;import com.mchange.v2.c3p0.ComboPooledDataSource;public class JdbcUtils {//使用的是默認的配置信息,注意給出c3p0-config.xml配置文件private static ComboPooledDataSource dataSource = new ComboPooledDataSource();//處理多線程的并發訪問問題,使用ThreadLocalprivate static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();public static Connection getConnection() throws SQLException{//不為Null說明開啟了事務,返回連接//先獲取自己線程的ConnectionConnection con = tl.get();if(con != null) return con;return dataSource.getConnection();}/*** 大方一點,給出連接池對象給你*/public static ComboPooledDataSource getDataSource(){return dataSource;}//給出三個方法/*** 開啟事務* 創建一個Connection,設置為手動提交* 保證DAO使用的就是這個事務的連接* 同時還需要保證下面兩個提交與回滾是同一個連接* 通過創建一個本類的連接成員* @throws SQLException */public static void startTransaction() throws SQLException{Connection con = tl.get();//開啟事務后con不再為nullcon = getConnection();con.setAutoCommit(false);//保存連接
tl.set(con);}/*** 提交事務* @throws SQLException */public static void commitTransaction() throws SQLException{Connection con = tl.get();if(con == null) throw new SQLException("事務未開啟,請勿提交!");con.commit();con.close();//清空連接con = null;//移除事務
tl.remove();}/*** 回滾事務* @throws SQLException */public static void rollbackTransaction() throws SQLException {Connection con = tl.get();if(con == null) throw new SQLException("事務未開啟,請勿回滾!");con.rollback();con.close();con = null;tl.remove();}/*** 用于釋放連接* @param connection* @throws SQLException */public static void releaseConnection(Connection connection) throws SQLException{//事務專用則不關閉,后續會有關閉//如果不是事務,則需要關閉Connection con = tl.get();//事務都沒有,直接關閉if(con == null) connection.close();//有事務,判斷是否相等,是否為專用連接if(con != connection) connection.close();}
}
?
一、簡易的入門:
common-dbutils是Apache對Jdbc的一個簡單的封裝,其中主要涉及的類有:
QueryRunner
ResultSetHandler
DbUtils
使用的依賴如下:
?
1.
重要類 QueryRunner (構造時提供數據源)
重要方法:int update(String sql,Object...params);增刪改
重載版本 int update(Connection con,String sql,Object...params);本方法不再管理con,由外部提供(保證是同一個)
T query(String sql,ResultSetHandler rsh,Object...params);查詢
重載版本類同上
給出一個使用的小例子:
package cn.itcast.demo;import java.sql.SQLException;import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;import cn.itcast.jdbcutils.JdbcUtils;/*** 測試commons-dbutils* @author jiangbei01**/
public class Demo02 {@Testpublic void testfun1() throws SQLException{QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());String sql = "INSERT INTO ab VALUES(?,?)";Object[] params = {8,"肖恩"};qr.update(sql, params);}
}
?
2.
給一張表對應一個類,字段與屬性對應起來
他會先得到ResultSet,然后調用handler方法轉換成需要的類型
接口ResultSetHandler,我們學習的實現類:
BeanHandler 構造器需要一個class參數,返回指定類型的javabean對象 ?一行記錄
BeanListHandler 構造器同上,由名稱知為多行,轉換成list對象,多個javabean ?多行記錄
MapHandler 把一行記錄轉換成一個map (如{name:zhangsan,age:20}) ?一行記錄
MapListHandler 同上對比,多個map的多行記錄,返回List<Map>,返回的也是一個List ?多行記錄
ScalarHandler 單行單列,通常與select count(*) from stu; 單行單列
這里使用裝飾者模式加上開頭改造的工具類,將QueryRunner稍加改造
package cn.itcast.jdbcutils;import java.sql.Connection;
import java.sql.SQLException;import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
/*** 這個類可以自身自己處理連接問題,可以通過jdbcUtils釋放連接(類方法會處理是否關閉)* @author jiangbei01**/
public class TxQueryRunner extends QueryRunner {@Overridepublic int[] batch(String sql, Object[][] params) throws SQLException {/** 得到連接* 執行父類方法* 釋放連接* 返回值*/Connection con = JdbcUtils.getConnection();int[] results = super.batch(con,sql, params);JdbcUtils.releaseConnection(con);return results;}@Overridepublic <T> T query(String sql, Object param, ResultSetHandler<T> rsh) throws SQLException {/** 得到連接* 執行父類方法* 釋放連接* 返回值*/Connection con = JdbcUtils.getConnection();T results = super.query(con,sql, param,rsh);JdbcUtils.releaseConnection(con);return results;}@Overridepublic <T> T query(String sql, Object[] params, ResultSetHandler<T> rsh) throws SQLException {Connection con = JdbcUtils.getConnection();T results = super.query(con,sql, params,rsh);JdbcUtils.releaseConnection(con);return results;}@Overridepublic <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {Connection con = JdbcUtils.getConnection();T results = super.query(con,sql, rsh,params);JdbcUtils.releaseConnection(con);return results;}@Overridepublic <T> T query(String sql, ResultSetHandler<T> rsh) throws SQLException {Connection con = JdbcUtils.getConnection();T results = super.query(con,sql, rsh);JdbcUtils.releaseConnection(con);return results;}@Overridepublic int update(String sql, Object... params) throws SQLException {Connection con = JdbcUtils.getConnection();int results = super.update(con,sql,params);JdbcUtils.releaseConnection(con);return results;}@Overridepublic int update(String sql, Object param) throws SQLException {Connection con = JdbcUtils.getConnection();int results = super.update(con,sql,param);JdbcUtils.releaseConnection(con);return results;}@Overridepublic int update(String sql) throws SQLException {Connection con = JdbcUtils.getConnection();int results = super.update(con,sql);JdbcUtils.releaseConnection(con);return results;}}
給出一個使用改造類的小例子:
package cn.itcast.jdbcutils;import java.sql.Connection;
import java.sql.SQLException;import org.apache.commons.dbutils.QueryRunner;public class AccountDAO {/*** 不能使用連接池* 要自己提供連接才能保證是同一個連接* @param name* @param money* @throws SQLException*/public static void update(String name, double money) throws SQLException{QueryRunner qr = new TxQueryRunner();String sql = "update account set balaence=balaence+? where name=?";Object[] params = {money,name};//給出參數并執行
qr.update(sql,params);/** 以下代碼新寫的Tx類已經完成,無需處理* Connection con = JdbcUtils.getConnection();* //釋放連接JdbcUtils.releaseConnection(con);*/}
}
?
并發訪問時產生的問題,可以使用ThreadLocal類(待更新詳細)進行解決,示例如下:
package cn.itcast.jdbcutils;import java.sql.Connection;
import java.sql.SQLException;import com.mchange.v2.c3p0.ComboPooledDataSource;public class JdbcUtils {//使用的是默認的配置信息,注意給出c3p0-config.xml配置文件private static ComboPooledDataSource dataSource = new ComboPooledDataSource();//處理多線程的并發訪問問題,使用ThreadLocalprivate static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();public static Connection getConnection() throws SQLException{//不為Null說明開啟了事務,返回連接//先獲取自己線程的ConnectionConnection con = tl.get();if(con != null) return con;return dataSource.getConnection();}/*** 大方一點,給出連接池對象給你*/public static ComboPooledDataSource getDataSource(){return dataSource;}//給出三個方法/*** 開啟事務* 創建一個Connection,設置為手動提交* 保證DAO使用的就是這個事務的連接* 同時還需要保證下面兩個提交與回滾是同一個連接* 通過創建一個本類的連接成員* @throws SQLException */public static void startTransaction() throws SQLException{Connection con = tl.get();//開啟事務后con不再為nullcon = getConnection();con.setAutoCommit(false);//保存連接
tl.set(con);}/*** 提交事務* @throws SQLException */public static void commitTransaction() throws SQLException{Connection con = tl.get();if(con == null) throw new SQLException("事務未開啟,請勿提交!");con.commit();con.close();//清空連接con = null;//移除事務
tl.remove();}/*** 回滾事務* @throws SQLException */public static void rollbackTransaction() throws SQLException {Connection con = tl.get();if(con == null) throw new SQLException("事務未開啟,請勿回滾!");con.rollback();con.close();con = null;tl.remove();}/*** 用于釋放連接* @param connection* @throws SQLException */public static void releaseConnection(Connection connection) throws SQLException{//事務專用則不關閉,后續會有關閉//如果不是事務,則需要關閉Connection con = tl.get();//事務都沒有,直接關閉if(con == null) connection.close();//有事務,判斷是否相等,是否為專用連接if(con != connection) connection.close();}
}
?