階篇_邁向標準開發(fā)
自己編寫dbutils工具( QueryRunner 、TxQueryRunner和JdbcUtils) (本文核心)
封裝成jar包后的標準開發(fā)--common-dbutisl和itcast-tools (本文核心)
數(shù)據(jù)庫使用MySQL數(shù)據(jù)庫,使用的表結(jié)構 :
tab_bin
t_user
account
t_customer
JDBC基礎代碼回顧
JDBC四大核心對象: 全部來自 java.sql 包下
DriverManager | 注冊驅(qū)動,獲取Connection對象 |
Connection | 連接對象,獲取preparedStatement |
PreparedStatement | sql語句發(fā)送器,執(zhí)行更新、查詢操作 |
ResultSet | 結(jié)果集,通過next()獲取結(jié)果 |
項目src文件下編寫dbconfig.properties配置文件:
name | value |
driverClassName | com.mysql.jdbc.Driver |
url | jdbc:mysql://localhost:3306/jdbc_test01 |
username | root |
password | 123456 |
@演示
JdbcUtils類_簡化代碼小工具
Dao類_操作/測試數(shù)據(jù)庫
c3p0數(shù)據(jù)庫連接池的使用
c3p0數(shù)據(jù)庫連接池 : 數(shù)據(jù)庫的很多連接對象都放在池中被管理著,誰用誰去租,用完歸還就行了。 c3p0就是一個比較不錯的池子 。
DataSource對象也在 java.sql 包下
項目src文件下編寫c3p0-config.xml配置文件(文件中也給出了oracle的配置模版):(@注意:配置文件的名稱c3p0-config.xml是一個官方給定的標準,不是隨意起的名字)
@演示
c3p0-config.xml
JdbcUtis工具類_c3p0版本
Test類_查看獲取的連接
大數(shù)據(jù)的插入(使用c3p0+JdbcUtls簡化代碼)
@解決的問題 如何向mysql中插入一部10M左右的.mp3文件 ???
MySQL中提供存儲大數(shù)據(jù)的類型如下:(@注意 標準SQL中提供的類型并非如下類型,請自行百度)
類型 | 長度 |
tinytext | 28-1 B(256B) |
text | 216-1B(64K) |
mediumtext | 224-1B(16M) |
longtext | 232-1B(4G) |
待插入文件地址 : D:\十年.mp3
待下載文件地址: E:\十年.mp3
@使用 c3p0數(shù)據(jù)庫連接池的使用 中的c3p0-config.xml 和JdbcUtils工具
@演示
BigData類_操作大數(shù)據(jù)
@可能出現(xiàn)錯誤 如果出現(xiàn)以下錯誤提示,請打開MySQL對于插入數(shù)據(jù)大小的限制。具體操作 : 在MySQL\MySQL Server 5.5\my.ini 文件中添加 max_allowed_packet = 16M
1 java.lang.RuntimeException: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (8498624 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.
批處理操作(使用c3p0+JdbcUtls簡化代碼)
批處理的意思是: PreparedStatement對象可以成批的發(fā)送SQL語句給服務器執(zhí)行,對象中有集合。 特別是在向數(shù)據(jù)庫中插入很多數(shù)據(jù)時,開啟了批處理后,1萬記錄只需要不到半秒,如果沒有開啟,則需要7分鐘。
MySQL中開啟批處理需要在url上添加參數(shù),即: jdbc:mysql://localhost:3306/jdbc_test01?rewriteBatchedStatements=true
@演示
批處理的JDBC代碼
數(shù)據(jù)庫中的事務(使用c3p0+JdbcUtls簡化代碼)
轉(zhuǎn)賬功能: A向B轉(zhuǎn)賬100元,數(shù)據(jù)庫操作是 : 1. A減少100元,2. B增加100。 若A減少100元,硬件崩潰,則B并沒有增 加100元,這是不行的,應該回滾到A還沒有減少100的時候 。 這就需要事務。
同一個事務中的多個操作,要么完全成功提交,要么完全失敗回滾到原點,不可能存在成功一半的情況,具有原子性、一致性、隔離性、持久性。 所以可以將以上的兩步操作放到一個事務中。
JDBC中與事務相關的對象是Connection 對象,該對象有三個方法來操作事務:
setAutoCommit(boolean) | false表示開啟事務 |
commit() | 提交事務 |
rollback() | 回滾事務 |
@注意 同一事務的所有操作,使用的是同一個Connection對象
@使用 c3p0數(shù)據(jù)庫連接池的使用 中的c3p0-config.xml 和JdbcUtils工具
@演示
AccountService類_轉(zhuǎn)賬業(yè)務/測試
AccountDao_sql操作
@事務并發(fā)的缺陷 多個事務并發(fā)執(zhí)行時,因為同時調(diào)用Connection對象而引發(fā)嚴重問題,造成臟讀、不可重復讀、虛讀的嚴重問題。 需要進行多線程并發(fā)控制
多線程并發(fā)控制的操作
@java中的并發(fā)問題 如果多個線程同時訪問同一個數(shù)據(jù)的時候,線程爭奪臨界資源數(shù)據(jù)引發(fā)問題 。 多個線程可描述為多個任務,例如: 同一個帳號在不同ATM機上取錢,這是兩個任務(也是兩個線程),兩個線程都要調(diào)用 Class 取錢{ private String 帳號 ; public void fun1() {} public void fun2() {} .... } 中的帳號變量(成員變量),就會出現(xiàn)讀寫問題。 一般來說,l臨界資源都是類中的成員變量,而非方法中的局部變量 。
JDBC操作中,因為多個事務同時調(diào)用Connection對象,會引起并發(fā)問題。
@解決問題 解決的方法可以用synchrozined{}同步塊 , 但是此法耗時嚴重。采用效率能提高150倍的ThreadLocal比較好。ThreadLocal類是一個泛型類,@思想 將臨界資源給每個線程都分配一份,來解決多個線程爭奪同一個資源而引發(fā)的難題。
ThreadLocal類java.lang包下已經(jīng)寫好的封裝類,直接調(diào)用即可 。 有三個方法: 分別是set()、get()和remove() 。 以下是自己編寫的模擬類,為了更好的理解該類的底層是怎么實現(xiàn)的
ThreadLocal類 核心功能
@演示 使用內(nèi)部類模擬多線程并發(fā)爭奪臨界資源來演示ThreadLocal的作用
ThreadLocal的測試
用ThreadLocal類解決JDBC中事務的并發(fā)問題放到TxQueryRunner類中解決
QueryRunner、TxQueryRunner和JdbcUtils(重點、本文核心)
QueryRunner的思想是: 把java中對數(shù)據(jù)庫的處理代碼寫到單獨的類QueryRunner中,Dao層只提供SQL模版和sql參數(shù),而TxQueryRunner負責繼承QueryRunner類輔助事務的處理 。JdbcUtils起到了真正的工具作 用,負責連接,事務等
@演示
@使用 c3p0數(shù)據(jù)庫連接池的使用 中的c3p0-config.xml
Customer
CustomerService
CustomerDao
JdbcUtils_工具類
QueryRunner_工具類
TxQueryRunner_工具類
ResultSetHandler_工具類
@download 項目下載http://files.cnblogs.com/files/zyuqiang/jdbcStudy_finalSummary.rar
封裝后的標準開發(fā)-------common-dbutils.jar和itcast-tools.jar(重點、本文核心)
commons-dbutils 是 Apache 組織提供的一個開源 JDBC 工具類庫,上述自己寫的QueryRunner工具類也是我對此官方的工具類庫做了一個簡單的核心功能的抽出,當然官方的工具類庫功能更加豐富 。 從此以后,我們開發(fā)不需要自己編寫工具類,而是導入common-dbutils.jar 來直接使用即可 . @注意 官網(wǎng)提供的 工具類庫 不包含TxQueryRunner和JdbcUtils工具,這兩個工具依然還需要我們自己動手實現(xiàn),不過也有非官方提供的封裝包,如傳智的itcast-tools.jar 。 可以拿來直接使用
@結(jié)果集處理器 common-dbutils包中提供了各種各樣的結(jié)果集處理器,可以處理查詢到的結(jié)果集,如封裝成實體類對象等。有如下的五種結(jié)果集處理器
BeanHandler | 結(jié)果集為單行 | 構造器需要一個Class類型的參數(shù),用來把查詢到的一行結(jié)果集轉(zhuǎn)換成指定類型的javaBean對象 | 常用 |
BeanListHandler | 結(jié)果集為多行 | 構造器也是需要一個Class類型的參數(shù),用來把查詢到的多行記錄一個記錄轉(zhuǎn)成一個javaBean對象,多個JavaBean構成轉(zhuǎn)List對象 | 常用 |
MapHandler | 結(jié)果集為單行 | 把一行結(jié)果集轉(zhuǎn)換Map對象 | 不常用 |
MapListHandler | 結(jié)果集為多行 | 把一行記錄轉(zhuǎn)換成一個Map,多行就是多個Map | 不常用 |
ScalarHandler | 結(jié)果集是單行單列 | 它返回一個Object,多用在求一共有多少個記錄上 | 常用 |
@演示 導入common-dbutils.jar 和 itcast-tools.jar(jar包在項目中,可以下載該項目找到),仍然@使用 c3p0數(shù)據(jù)庫連接池的使用 中的c3p0-config.xml
Customer
CustomerService
CustomerDao
TestDemo
也可以批量添加數(shù)據(jù)
1 private QueryRunner qr = new TxQueryRunner(); 2 /** 3 * 添加新客戶 4 * 批處理 5 * @param cstm,num是批量插入記錄的行數(shù) 6 * @throws SQLException 7 */ 8 public void add(Customer cstm , int num) throws SQLException { 9 /*10 * 1. 創(chuàng)建TxQueryRunner對象 11 * 2. 準備SQL模版 12 * 3. 將參數(shù)存入?yún)?shù)數(shù)組 13 * 4. 調(diào)用TxQueryRunner類中batch方法 進行插入操作14 */15 String sql ="insert into t_customer values(?,?,?)";16 Object[][] params = new Object[num][];17 for(int i=0;i<params.length;i++){18 params[i]=new Object[]{cstm.getUsername()+i,19 cstm.getAge()+i,20 cstm.getBalance()};21 }22 // Object[] params = {cstm.getUsername(),23 // cstm.getAge(),24 // cstm.getBalance()};25 qr.batch(sql, params); 26 }
@download 項目下載http://files.cnblogs.com/files/zyuqiang/jdbcStudy_finalSummary_Commons.rar
http://www.cnblogs.com/zyuqiang/p/7218083.html