相關連接:Jdbc調用存儲過程java
咱們經常使用的操做數據庫語言SQL語句在執行的時候須要先編譯,而後執行,而存儲過程(Stored Procedure)是在大型數據庫系統中,一組爲了完成特定功能的SQL 語句集,存儲在數據庫中,通過第一次編譯後再次調用不須要再次編譯,用戶經過指定存儲過程的名字並給出參數(若是該存儲過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序都應該用到存儲過程。mysql
一個存儲過程是一個可編程的函數,它在數據庫中建立並保存。它能夠有SQL語句和一些特殊的控制結構組成。當但願在不一樣的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是很是有用的。數據庫中的存儲過程能夠看作是對編程中面向對象方法的模擬。它容許控制數據的訪問方式。sql
存儲過程一般有如下優勢:數據庫
(1).存儲過程加強了SQL語言的功能和靈活性。存儲過程能夠用流控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。apache
(2).存儲過程容許標準組件是編程。存儲過程被建立後,能夠在程序中被屢次調用,而沒必要從新編寫該存儲過程的SQL語句。並且數據庫專業人員能夠隨時對存儲過程進行修改,對應用程序源代碼毫無影響。編程
(3).存儲過程能實現較快的執行速度。若是某一操做包含大量的Transaction-SQL代碼或分別被屢次執行,那麼存儲過程要比批處理的執行速度快不少。由於存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,而且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。tomcat
(4).存儲過程能過減小網絡流量。針對同一個數據庫對象的操做(如查詢、修改),若是這一操做所涉及的Transaction-SQL語句被組織程存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增長了網絡流量並下降了網絡負載。安全
(5).存儲過程可被做爲一種安全機制來充分利用。系統管理員經過執行某一存儲過程的權限進行限制,可以實現對相應的數據的訪問權限的限制,避免了非受權用戶對數據的訪問,保證了數據的安全。服務器
簡單來講它的好處主要是:網絡
1.因爲數據庫執行動做時,是先編譯後執行的。然而存儲過程是一個編譯過的代碼塊,因此執行效率要比T-SQL語句高。
2.一個存儲過程在程序在網絡中交互時能夠替代大堆的T-SQL語句,因此也能下降網絡的通訊量,提升通訊速率。
3.經過存儲過程可以使沒有權限的用戶在控制之下間接地存取數據庫,從而確保數據的安全。
在數據庫新建存儲過程:
注意:建立的存儲過程名稱不要加「()」,否則在調用存儲過程時會提示以下錯誤:
代碼示例:ProduceDao.java
1 package com.study.dao; 2 3 import java.sql.CallableStatement; 4 import java.sql.Connection; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 8 import com.study.db.DBUtil; 9 10 /** 11 * @Description: 存儲過程 12 * @author: Qian 13 * @date: 2016-4-3 下午4:15:24 14 */ 15 public class ProduceDao { 16 public static void select_nofilter() throws SQLException{ 17 //1.得到鏈接 18 Connection conn = DBUtil.getConnection(); 19 //2.得到CallableStatement 20 CallableStatement cs = conn.prepareCall("call sp_select_nofilter()"); 21 //3.執行存儲過程 22 cs.execute(); 23 //4.處理返回的結果:結果集,出參 24 ResultSet rs = cs.getResultSet(); 25 /*遍歷結果集*/ 26 while(rs.next()){ 27 System.out.println(rs.getString("user_name")+":"+rs.getString("email")); 28 } 29 } 30 }
JDBCTestProduce.java
1 package com.study.test; 2 3 import java.sql.SQLException; 4 5 import com.study.dao.ProduceDao; 6 7 /** 8 * @Description: 測試存儲過程 9 * @author: Qian 10 * @date: 2016-4-3 下午4:24:10 11 */ 12 public class JDBCTestProduce { 13 public static void main(String[] args) throws SQLException { 14 ProduceDao dao=new ProduceDao(); 15 dao.select_nofilter(); 16 } 17 }
運行結果:
調用存儲過程:傳個空字符
傳個「小」
1 //JDBC 調用帶輸入參數的存儲過程 2 public static List<Goddess> select_filter(String sp_name) throws SQLException{ 3 List<Goddess> result=new ArrayList<Goddess>(); 4 //1.得到鏈接 5 Connection conn = DBUtil.getConnection(); 6 //2.得到CallableStatement 7 CallableStatement cs = conn.prepareCall("call sp_select_filter(?)"); 8 cs.setString(1, sp_name); 9 //3.執行存儲過程 10 cs.execute(); 11 //4.處理返回的結果:結果集,出參 12 ResultSet rs = cs.getResultSet(); 13 Goddess g=null; 14 while(rs.next()){//若是對象中有數據,就會循環打印出來 15 g=new Goddess(); 16 g.setId(rs.getInt("id")); 17 g.setUserName(rs.getString("user_name")); 18 g.setAge(rs.getInt("age")); 19 result.add(g); 20 } 21 return result; 22 }
測試:
1 public class JDBCTestProduce { 2 public static void main(String[] args) throws SQLException { 3 ProduceDao dao=new ProduceDao(); 4 // dao.select_nofilter(); 5 String sp_name=""; 6 List<Goddess> res=null; 7 res=dao.select_filter(sp_name); 8 for (int i = 0; i < res.size(); i++) { 9 System.out.println(res.get(i).getId()+":"+res.get(i).getUserName()+":"+res.get(i).getAge()); 10 11 } 12 } 13 }
調用存儲過程:
1 //JDBC 調用含輸出參數存儲過程 2 public static Integer select_count() throws SQLException{ 3 Integer count=0; 4 //1.得到鏈接 5 Connection conn = DBUtil.getConnection(); 6 //2.得到CallableStatement,prepareStatement,statement 7 CallableStatement cs = conn.prepareCall("call sp_select_count(?)"); 8 cs.registerOutParameter(1, Types.INTEGER);//註冊輸出參數,第二個參數是告訴JDBC,輸出參數的類型 9 //3.執行存儲過程 10 cs.execute(); 11 //4.處理返回的結果:這個不是結果集,是出參 12 count=cs.getInt(1); 13 return count; 14 }
測試:
1 package com.study.test; 2 3 import java.sql.SQLException; 4 import java.util.List; 5 6 import com.study.dao.ProduceDao; 7 import com.study.model.Goddess; 8 9 /** 10 * @Description: 測試存儲過程 11 * @author: Qian 12 * @date: 2016-4-3 下午4:24:10 13 */ 14 public class JDBCTestProduce { 15 public static void main(String[] args) throws SQLException { 16 // ProduceDao dao=new ProduceDao(); 17 // dao.select_nofilter(); 18 /*String sp_name=""; 19 List<Goddess> res=null; 20 res=dao.select_filter(sp_name); 21 for (int i = 0; i < res.size(); i++) { 22 System.out.println(res.get(i).getId()+":"+res.get(i).getUserName()+":"+res.get(i).getAge()); 23 24 }*/ 25 String sp_name="小"; 26 List<Goddess> res=null; 27 Integer count=0; 28 //帶輸入參數的存儲過程 29 /*res=select_filter(sp_name); 30 showResult(res);*/ 31 count=select_count(); 32 System.out.println(count); 33 } 34 35 public static List<Goddess> select_filter(String sp_name) throws SQLException{ 36 ProduceDao dao=new ProduceDao(); 37 return dao.select_filter(sp_name); 38 } 39 public static Integer select_count() throws SQLException{ 40 ProduceDao dao=new ProduceDao(); 41 return dao.select_count(); 42 } 43 44 public static void showResult(List<Goddess> result){ 45 for (int i = 0; i < result.size(); i++) { 46 System.out.println(result.get(i).getId()+":"+result.get(i).getUserName()+":"+result.get(i).getAge()); 47 48 } 49 } 50 }
事務的概念:
事務(transaction)是做爲單個邏輯工做單元執行的一系列操做。這些操做做爲一個總體一塊兒向系統提交,要麼都執行、要麼都不執行。
事務的特色:
一、原子性(Atomicity)
事務是一個完整的操做。不能對它進行再分割,是最小的一個單元。
二、一致性(Consistency)
當事務完成時,數據必須處於一致狀態。
(例如銀行轉帳,張三要給李四轉100元。則第一步張三的帳戶須要減去100元,第二步李四的帳戶須要加上100元。這是兩個操做,可是應該在一個事務裏面。若是沒有在一個事務裏面,張三減去100,李四並無增長100,那這樣數據就出現了不一致性,張三的錢跑哪去了呢 )
三、隔離性(Isolation)
對數據進行修改的全部併發事務是彼此隔離的。
(好比業務A:張三減100,李四加100;同時業務B也是張三減100,李四加100進行操做。業務A和B是同時的,這時候就出現了併發,這個時候是怎麼變化的呢?當業務員A進行操做的時候,業務員B就要等待……就是同一時間對數據庫的操做要保持一個事務的鎖定。也就是說我在作的時候,別人是不能作的。我作完了以後別人才能作,彼此之間是隔離的)
四、永久性(Durability)
事務完成後,它對數據庫的修改被永久保持。
①咱們經過提交commit()或是回退rollback()來管理事務的操做。
當事務完成的時候,咱們經過commit將事務提交到數據庫之中,而後數據庫會變成持久化的,咱們的數據就會永久保存了。
若是採用rollback的話,事務回滾,好比說咱們插入的數據、更新的數據都會變成原來沒有更新、沒有插入時的樣子。
②事務操做默認是自動提交
當咱們調用完insert語句,不用調用commit語句,本身就提交了。
③能夠調用setAutoCommit(false) 來禁止自動提交。
首先咱們要注意,在JDBC中,事務操做默認是自動提交。也就是說,一條對數據庫的更新表達式表明一項事務操做。操做成功後,系統將自動調用commit()來提交,不然將調用rollback()來回退。
其次,在JDBC中,能夠經過調用setAutoCommit(false)來禁止自動提交。以後就能夠把多個數據庫操做的表達式做爲一個事務,在操做完成 後調用commit()來進行總體提交。假若其中一個表達式操做失敗,都不會執行到commit(),而且將產生響應的異常。此時就能夠在異常捕獲時調用 rollback()進行回退。這樣作能夠保持屢次更新操做後,相關數據的一致性。
try { conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;User=JavaDB;Password=javadb;DatabaseName=northwind); //點禁止自動提交,設置回退 conn.setAutoCommit(false); stmt = conn.createStatement(); //數據庫更新操做1 stmt.executeUpdate(「update firsttable Set Name='testTransaction' Where ID = 1」); //數據庫更新操做2 stmt.executeUpdate(「insert into firsttable ID = 12,Name = 'testTransaction2'」); //事務提交 conn.commit(); }catch(Exception ex) { ex.printStackTrace(); try { //操做不成功則回退 conn.rollback(); }catch(Exception e){ e.printStackTrace(); } }
這樣上面這段程序的執行,或者兩個操做都成功,或者兩個都不成功,讀者能夠本身修改第二個操做,使其失敗,以此來檢查事務處理的效果。
咱們在前面還提到了JDBC對事務所支持的隔離級別,下面將更詳細進行討論。
JDBC API支持事務對數據庫的加鎖,而且提供了5種操做支持,2種加鎖密度。
5種加鎖支持爲:
static int TRANSACTION_NONE = 0;
static int TRANSACTION_READ_UNCOMMITTED = 1;
static int TRANSACTION_READ_COMMITTED = 2;
static int TRANSACTION_REPEATABLE_READ = 4;
static int TRANSACTION_SERIALIZABLE = 8;
具體的說明見表4-2。
2種加鎖密度:
最後一項爲表加鎖,其他3~4項爲行加鎖。
「髒」數據讀寫(Dirty Reads):當一個事務修改了某一數據行的值而未提交時,另外一事務讀取了此行值。假若前一事務發生了回退,則後一事務將獲得一個無效的值(「髒」數據)。
重複讀寫(Repeatable Reads):當一個事務在讀取某一數據行時,另外一事務同時在修改此數據行。則前一事務在重複讀取此行時將獲得一個不一致的值。
錯 誤(映像)讀寫(Phantom Reads):當一個事務在某一表中進行數據查詢時,另外一事務剛好插入了知足了查詢條件的數據行。則前一事務在重複讀取知足條件的值時,將獲得一個額外的 「影像」值。JDBC根據數據庫提供的默認值來設置事務支持及其加鎖,固然,也能夠手工設置:
setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);
能夠查看數據庫的當前設置:
getTransactionIsolation ()
須要注意的是,在進行手動設置時,數據庫及其驅動程序必須得支持相應的事務操做操做才行。
上 述設置隨着值的增長,其事務的獨立性增長,更能有效地防止事務操做之間的衝突,同時也增長了加鎖的開銷,下降了用戶之間訪問數據庫的併發性,程序的運行效 率也會隨之下降。所以得平衡程序運行效率和數據一致性之間的衝突。通常來講,對於只涉及到數據庫的查詢操做時,能夠採用 TRANSACTION_READ_UNCOMMITTED方式;對於數據查詢遠多於更新的操做,能夠採用 TRANSACTION_READ_COMMITTED方式;對於更新操做較多的,能夠採用TRANSACTION_REPEATABLE_READ;在 數據一致性要求更高的場合再考慮最後一項,因爲涉及到表加鎖,所以會對程序運行效率產生較大的影響。
另外,在Oracle中數據庫驅動對事務處理的默認值是TRANSACTION_NONE,即不支持事務操做,因此須要在程序中手動進行設置。總之,JDBC提供的對數據庫事務操做的支持是比較完整的,經過事務操做能夠提升程序的運行效率,保持數據的一致性。
鏈接池產生的背景:
數據庫鏈接是一種重要資源。大部分很重要的數據都存在數據庫裏,那麼在產生鏈接池以前,咱們鏈接數據庫的方式:直連。(獲取鏈接->使用->關閉鏈接)程序小的話能夠採用這種方式,可是若是程序很大,好比大型網站,它可能每分鐘或者每秒變化量在100萬次,就是說同時訪問數據庫有100萬個用戶,這時候若是咱們不用鏈接池的話,咱們就須要建立100萬個鏈接這樣的話就會對數據庫形成很大的壓力,若是數據庫承受不了的話就崩潰了,服務器也崩潰了,網站就癱瘓了。
即:
①數據庫鏈接是一種重要資源;
②頻繁的鏈接數據庫會增長數據庫的壓力;
③爲解決以上問題出現鏈接池技術。
(池子裏保持必定數量的鏈接,當使用時就從池子中拿一個鏈接出來,當使用完鏈接後就把它釋放到池子裏。當你同時訪問數據庫人不少的時候,這個時候鏈接不夠用,就須要等待,減小數據庫的壓力)
經常使用的開源數據庫鏈接池:
一、首先,導入相關jar包:
二、在項目根目錄增長配置文件:dbcp.properties
這個屬性文件的內容以下:
三、配置並測試dbcp鏈接
DBCPUtil.java
1 package com.study.db; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 import java.util.Properties; 6 7 import javax.sql.DataSource; 8 9 import org.apache.commons.dbcp2.BasicDataSource; 10 import org.apache.commons.dbcp2.BasicDataSourceFactory; 11 /** 12 * @Description: DBCP配置類 13 * @author: Qian 14 * @date: 2016-4-4 上午8:57:49 15 */ 16 public class DBCPUtil { 17 /**數據源,static*/ 18 private static DataSource DS; 19 private static final String configFile="/dbcp.properties";//配置文件 20 21 /**從數據源得到一個鏈接*/ 22 /** 23 * @Description: TODO 24 * @param @return 設定文件 25 * @return Connection 返回類型 26 * @author Qian 27 * @date 2016-4-4 上午9:11:07 28 */ 29 public Connection getConn(){ 30 Connection conn=null; 31 if(DS !=null){ 32 try { 33 conn=DS.getConnection();//從數據源裏面拿到鏈接 34 } catch (Exception e) { 35 e.printStackTrace(System.err); 36 } 37 try { 38 conn.setAutoCommit(false);//關閉鏈接的自動提交 39 } catch (SQLException e) { 40 e.printStackTrace(); 41 } 42 return conn; 43 } 44 return conn; 45 } 46 47 /**默認的構造函數*/ 48 /** 49 * @Description: TODO 50 * @param 51 * @return 52 * @author Qian 53 * @date 2016-4-4 上午9:17:02 54 */ 55 public DBCPUtil(){ 56 initDbcp(); 57 } 58 59 private static void initDbcp(){ 60 Properties pops=new Properties(); 61 try { 62 pops.load(Object.class.getResourceAsStream(configFile));//讀取配置文件 63 DS=BasicDataSourceFactory.createDataSource(pops);//經過BasicDataSourceFactory提供的工廠類,拿到DataSource數據源 64 } catch (Exception e) { 65 e.printStackTrace(); 66 } 67 } 68 /*構造函數,初始化了DS,指定數據庫*/ 69 public DBCPUtil(String connectURI){ 70 initDS(connectURI); 71 } 72 73 /*構造函數,初始化了DS,指定全部參數*/ 74 public DBCPUtil(String connectURI,String userName,String passWord,String driverClass,int initialSize,int maxIdle,int minIdle,int maxWait){ 75 initDS(connectURI,userName,passWord,driverClass,initialSize,maxIdle,minIdle,maxWait); 76 } 77 78 /** 79 * @Description: 建立數據源,除了數據外,都是用硬編碼默認參數 80 * @param @param connectURI 數據庫 81 * @return 82 * @author Qian 83 * @date 2016-4-4 上午9:47:18 84 */ 85 public static void initDS(String connectURI){ 86 initDS(connectURI, "root", "root", "com.mysql.jdbc.Driver", 10, 20, 5, 1000); 87 } 88 89 /** 90 * @Description: 91 * @param @param connectURI 數據庫 92 * @param @param userName 用戶名 93 * @param @param passWord 密碼 94 * @param @param driverClass 驅動 95 * @param @param initialSize 初始化鏈接數 96 * @param @param maxIdle 最大鏈接數 97 * @param @param minIdle 最小鏈接數 98 * @param @param maxWait 超時等待時間(得到鏈接的最大等待毫秒數) 99 * @return 100 * @author Qian 101 * @date 2016-4-4 上午9:45:18 102 */ 103 public static void initDS(String connectURI,String userName,String passWord,String driverClass, 104 int initialSize,int maxIdle,int minIdle,int maxWait){ 105 BasicDataSource ds=new BasicDataSource();//new 一個數據源 106 ds.setDriverClassName(driverClass); 107 ds.setUsername(userName); 108 ds.setPassword(passWord); 109 ds.setUrl(connectURI); 110 ds.setInitialSize(initialSize);//初始的鏈接數 111 ds.setMaxIdle(maxIdle); 112 ds.setMaxWaitMillis(maxWait); 113 ds.setMinIdle(minIdle); 114 DS = ds; 115 } 116 }
GoddessDao.java
1 //查詢單個女神(根據id去查詢) 2 public Goddess get(Integer id) throws SQLException{ 3 Goddess g=null; 4 Connection con=DBUtil.getConnection();//首先拿到數據庫的鏈接 5 String sql="" + 6 "select * from imooc_goddess "+ 7 "where id=?";//參數用?表示,至關於佔位符;用mysql的日期函數current_date()來獲取當前日期 8 //預編譯sql語句 9 PreparedStatement psmt = con.prepareStatement(sql); 10 //先對應SQL語句,給SQL語句傳遞參數 11 psmt.setInt(1, id); 12 //執行SQL語句 13 /*psmt.execute();*///execute()方法是執行更改數據庫操做(包括新增、修改、刪除);executeQuery()是執行查詢操做 14 ResultSet rs = psmt.executeQuery();//返回一個結果集 15 //遍歷結果集 16 while(rs.next()){ 17 g=new Goddess(); 18 g.setId(rs.getInt("id")); 19 g.setUserName(rs.getString("user_name")); 20 g.setAge(rs.getInt("age")); 21 g.setSex(rs.getInt("sex")); 22 //rs.getDate("birthday")得到的是java.sql.Date類型。注意:java.sql.Date類型是java.util.Date類型的子集,因此這裏不須要進行轉換了。 23 g.setBirthday(rs.getDate("birthday")); 24 g.setEmail(rs.getString("email")); 25 g.setMobile(rs.getString("mobile")); 26 g.setCreateUser(rs.getString("create_user")); 27 g.setCreateDate(rs.getDate("create_date")); 28 g.setUpdateUser(rs.getString("update_user")); 29 g.setUpdateDate(rs.getDate("update_date")); 30 g.setIsDel(rs.getInt("isdel")); 31 } 32 return g; 33 } 34 35 //查詢單個女神(根據id去查詢) 36 public Goddess getByDbcp(Integer id) throws SQLException{ 37 DBCPUtil db=new DBCPUtil(); 38 Goddess g=null; 39 Connection con=db.getConn();//首先拿到數據庫的鏈接 40 String sql="" + 41 "select * from imooc_goddess "+ 42 "where id=?";//參數用?表示,至關於佔位符;用mysql的日期函數current_date()來獲取當前日期 43 //預編譯sql語句 44 PreparedStatement psmt = con.prepareStatement(sql); 45 //先對應SQL語句,給SQL語句傳遞參數 46 psmt.setInt(1, id); 47 //執行SQL語句 48 /*psmt.execute();*///execute()方法是執行更改數據庫操做(包括新增、修改、刪除);executeQuery()是執行查詢操做 49 ResultSet rs = psmt.executeQuery();//返回一個結果集 50 //遍歷結果集 51 while(rs.next()){ 52 g=new Goddess(); 53 g.setId(rs.getInt("id")); 54 g.setUserName(rs.getString("user_name")); 55 g.setAge(rs.getInt("age")); 56 g.setSex(rs.getInt("sex")); 57 //rs.getDate("birthday")得到的是java.sql.Date類型。注意:java.sql.Date類型是java.util.Date類型的子集,因此這裏不須要進行轉換了。 58 g.setBirthday(rs.getDate("birthday")); 59 g.setEmail(rs.getString("email")); 60 g.setMobile(rs.getString("mobile")); 61 g.setCreateUser(rs.getString("create_user")); 62 g.setCreateDate(rs.getDate("create_date")); 63 g.setUpdateUser(rs.getString("update_user")); 64 g.setUpdateDate(rs.getDate("update_date")); 65 g.setIsDel(rs.getInt("isdel")); 66 } 67 return g; 68 }
測試:
1 package com.study.test; 2 3 import java.util.Date; 4 5 import com.study.dao.GoddessDao; 6 import com.study.model.Goddess; 7 8 /**@Description: 測試用DBCP鏈接數據庫 9 * @author: Qian 10 * @date: 2016-4-4 上午9:53:53 11 */ 12 public class TestDbcp { 13 14 /**@Description: TODO 15 * @param @param args 16 * @return 17 * @author Qian 18 * @throws Exception 19 * @date 2016-4-4 上午9:53:53 20 */ 21 public static void main(String[] args) throws Exception { 22 //1.經過普通方式操做數據庫 23 Date a=new Date(); 24 get(); 25 Date b=new Date(); 26 System.out.println(b.getTime()-a.getTime()); 27 28 //2.經過DBCP鏈接池的方式操做數據庫 29 Date c=new Date(); 30 get(); 31 Date d=new Date(); 32 System.out.println(d.getTime()-c.getTime()); 33 34 /** 35 * 經過運行,發現第二種方式明顯要比第一種用時少 36 */ 37 } 38 39 public static void get() throws Exception{ 40 GoddessDao dao=new GoddessDao(); 41 Goddess g=dao.get(1); 42 System.out.println(g.toString()); 43 } 44 45 public static void getByDbcp() throws Exception{ 46 GoddessDao dao=new GoddessDao(); 47 Goddess g=dao.getByDbcp(1); 48 System.out.println(g.toString()); 49 } 50 }
c3p0是一個開源的JDBC鏈接池,它實現了數據源和JNDI綁定,支持JDBC3和JDBC2的標準擴展。目前使用它的開源項目有Hibernate,Spring等。
默認狀況下(即沒有配置鏈接池的狀況下),Hibernate會採用內建的鏈接池。但這個鏈接池性能不佳,所以官方也只是建議僅在開發環境下使用。Hibernate支持第三方的鏈接池,官方推薦的鏈接池是C3P0,Proxool。
一、導入相關jar包:
注:在tomcat或者項目中引入最新版的C3P0的JAR包(我是用的是c3p0-0.9.2.1.jar)
若是啓動時報類沒有找到:Caused by: java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector,
則須要加入mchange-commons-java-0.2.3.4.jar。
二、在項目根目錄增長配置文件:c3p0.properties
1 c3p0.driverClass=com.mysql.jdbc.Driver 2 c3p0.jdbcUrl=jdbc:mysql://localhost:3306/demo_jdbc 3 c3p0.user=root 4 c3p0.password=root
三、編寫類文件,建立鏈接池
C3P0Util.java
1 package com.study.db; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 6 import com.mchange.v2.c3p0.ComboPooledDataSource; 7 8 /**@Description: c3p0數據源配置類 9 * @author: Qian 10 * @date: 2016-4-4 上午10:40:01 11 */ 12 public class C3P0Util { 13 //建立一個數據源 14 private static ComboPooledDataSource ds=new ComboPooledDataSource(); 15 16 public static Connection getConn(){ 17 try { 18 return ds.getConnection(); 19 } catch (SQLException e) { 20 throw new RuntimeException(e); 21 } 22 } 23 }
TestC3p0.java
1 package com.study.test; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 6 import com.study.db.C3P0Util; 7 8 /**@Description: 測試C3P0 9 * @author: Qian 10 * @date: 2016-4-4 上午10:43:11 11 */ 12 public class TestC3p0 { 13 14 /**@Description: TODO 15 * @param @param args 16 * @return 17 * @author Qian 18 * @throws SQLException 19 * @date 2016-4-4 上午10:43:11 20 */ 21 public static void main(String[] args) throws SQLException { 22 Connection con=C3P0Util.getConn(); 23 System.out.println(con.getCatalog()); 24 25 } 26 27 }
能夠仿照上面dbcp來測試c3p0鏈接池。
DBCP和C3P0的相同點:
DBCP和C3P0的不一樣點:
上面介紹的都是手工的鏈接數據庫,寫SQL語句。這部分的替代產品會替代咱們的這些工做。
替代工具:
從字面意思能夠理解爲:通用的數據庫工具類。
Apache組織提供的一個開源JDBC工具類庫,對傳統操做數據庫的類進行二次封裝,能夠把結果集轉化成List。
特色:
核心接口:
示例:
是一種Java語言下的對象關係映射解決方案。它是一種自由、開源的軟件。
優勢:
缺點:
若是對大量的數據進行頻繁的操做,性能效率比較低,不如直接使用JDBC。(由於Hibernate作了完整的封裝,因此效率可能會低。)
核心接口:
示例:
*.hbm.xml
插入:
Mybatis是支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。
特色:
示例:
userMapper.xml示例