JDBC的擴展知識點總結
一、數(shù)據(jù)庫的事務
1.1 事務概述
- 事務:一組邏輯操作單元,使數(shù)據(jù)從一種狀態(tài)變換到另一種狀態(tài)
- 事務處理(事務操作):保證所有事務都作為一個工作單元來執(zhí)行,即使出現(xiàn)了故障,都不能改變這種執(zhí)行方式。當在一個事務中執(zhí)行多個操作時,要么所有的事務都被提交(commit),那么這些修改就永久地保存下來;要么數(shù)據(jù)庫管理系統(tǒng)將放棄所作的所有修改,整個事務回滾(rollback)到最初狀態(tài)
- 為確保數(shù)據(jù)庫中數(shù)據(jù)的一致性,數(shù)據(jù)的操縱應當是離散的成組的邏輯單元:當它全部完成時,數(shù)據(jù)的一致性可以保持,而當這個單元中的一部分操作失敗,整個事務應全部視為錯誤,所有從起始點以后的操作應全部回退到開始狀態(tài)
- 舉個栗子,當小明給小紅轉賬時,因為種種原因沒有轉賬成功,小明的錢減少了,小紅卻沒有收到錢,此時就需要事務回滾,否則小明就得哭死…
1.2 事務的屬性
事務的ACID(acid)屬性
- 原子性(Atomicity)
- 原子性是指事務是一個不可分割的工作單位,事務中的操作要么都發(fā)生,要么都不發(fā)生。
- 一致性(Consistency)
- 事務必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另外一個一致性狀態(tài)。
- 隔離性(Isolation)
- 事務的隔離性是指一個事務的執(zhí)行不能被其他事務干擾,即一個事務內部的操作及使用的數(shù)據(jù)對并發(fā)的其他事務是隔離的,并發(fā)執(zhí)行的各個事務之間不能互相干擾。
- 持久性(Durability)
- 持久性是指一個事務一旦被提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的,接下來的其他操作和數(shù)據(jù)庫故障不應該對其有任何影響
1.3 JDBC事務處理
當一個連接對象被創(chuàng)建時,默認情況下是自動提交事務:每次執(zhí)行一個 SQL 語句時,如果執(zhí)行成功,就會向數(shù)據(jù)庫自動提交,而不能回滾
為了讓多個 SQL 語句作為一個事務執(zhí)行:
1. 調用 Connection 對象的 setAutoCommit(false); 以取消自動提交事務
2.在所有的 SQL 語句都成功執(zhí)行后,調用 commit(); 方法提交事務
3.在出現(xiàn)異常時,調用 rollback(); 方法回滾事務
4.若此時 Connection 沒有被關閉, 則需要恢復其自動提交狀態(tài)
1.4 數(shù)據(jù)庫事務使用的過程
使用數(shù)據(jù)庫的事務,我們需要配合異常處理try
public void testJDBCTransaction() { Connection conn = null; try { // 1.獲取數(shù)據(jù)庫連接 conn = JDBCUtils.getConnection(); // 2.開啟事務 conn.setAutoCommit(false); // 3.進行數(shù)據(jù)庫操作 // 4.若沒有異常,則提交事務 conn.commit(); } catch (Exception e) { e.printStackTrace(); // 5.若有異常,則回滾事務 try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); }} finally { JDBCUtils.close(null, null, conn); } }
1.5 使用數(shù)據(jù)庫事務的好處
使用COMMIT 和 ROLLBACK語句,我們可以:
- 確保數(shù)據(jù)完整性。
- 數(shù)據(jù)改變被提交之前預覽。
- 將邏輯上相關的操作分組
提交或回滾前的數(shù)據(jù)狀態(tài)
- 改變前的數(shù)據(jù)狀態(tài)是可以恢復的
- 執(zhí)行 DML 操作的用戶可以通過 SELECT 語句查詢提交或回滾之前的修正
- 其他用戶不能看到當前用戶所做的改變,直到當前用戶結束事務。
- DML語句所涉及到的行被鎖定, 其他用戶不能操作
提交后的數(shù)據(jù)狀態(tài)
- 數(shù)據(jù)的改變已經被保存到數(shù)據(jù)庫中。
- 改變前的數(shù)據(jù)已經丟失。
- 所有用戶可以看到結果。
- 鎖被釋放, 其他用戶可以操作涉及到的數(shù)據(jù)
說了這么多,還是使用代碼來舉例說明更加清晰(數(shù)據(jù)庫連接的JDBCUtils類上一章寫過了):
package com.company.jdbcDemo; import com.company.jdbcDemo.JDBCUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /* AA給CC轉賬1000 AA 2000 CC 2000 try{ 開啟事務 AA -= 1000 System.out.println(1/0); CC += 1000 提交(一旦提交數(shù)據(jù)不能再回滾(撤銷)) }catch(Exception e){ 事務回滾(撤銷) } CREATE TABLE account( NAME VARCHAR(20), balance INT ) */ public class AccountDemo { public static void main(String[] args) throws SQLException { //1.獲取數(shù)據(jù)庫連接對象 Connection connection = JDBCUtils.getConnection(); PreparedStatement ps = null; try { //2.開啟事物--禁止自動提交 connection.setAutoCommit(false); //------------------------------------------------------------------- //3.做具體的操作---執(zhí)行sql語句 //預編譯 String sql = "update account set balance=? where name=?"; ps = connection.prepareStatement(sql); //給占位符賦值 ps.setInt(1, 1000); ps.setString(2, "aa"); //執(zhí)行sql ps.executeUpdate(); System.out.println(1 / 0); //給占位符賦值 ps.setInt(1, 3000); ps.setString(2, "cc"); //執(zhí)行sql ps.executeUpdate(); //------------------------------------------------------------------- //4.事務提交 connection.commit(); }catch (Exception e){ e.printStackTrace(); //5.事務回滾 connection.rollback(); }finally { //6.允許自動提交 connection.setAutoCommit(true); //7.關閉資源----最后關閉資源 JDBCUtils.close(ps,connection); } } }
二、數(shù)據(jù)庫連接池
概述
前面我們的示例代碼中,一直在調用我寫的那個JDBCUtils類來完成數(shù)據(jù)庫的連接,如果我們在別的工程中,就需要復制一下我的那個類,并且我寫的那個也不是很嚴謹,我前面實現(xiàn)的數(shù)據(jù)庫連接方式存在以下問題:
- 普通的JDBC數(shù)據(jù)庫連接使用 DriverManager 來獲取,每次向數(shù)據(jù)庫建立連接的時候都要將 Connection 加載到內存中,再驗證用戶名和密碼
- 數(shù)據(jù)庫的連接資源并沒有得到很好的重復利用.若同時有幾百人甚至幾千人在線,頻繁的進行數(shù)據(jù)庫連接操作將占用很多的系統(tǒng)資源,嚴重的甚至會造成服務器的崩潰
- 對于每一次數(shù)據(jù)庫連接,使用完后都得斷開。否則,如果程序出現(xiàn)異常而未能關閉,將會導致數(shù)據(jù)庫系統(tǒng)中的內存泄漏,最終將導致重啟數(shù)據(jù)庫
- 這種開發(fā)不能控制被創(chuàng)建的連接對象數(shù),系統(tǒng)資源會被毫無顧及的分配出去,如連接過多,也可能導致內存泄漏,服務器崩潰
使用數(shù)據(jù)庫連接池
- 數(shù)據(jù)庫連接池的基本思想就是為數(shù)據(jù)庫連接建立一個“緩沖池”。預先在緩沖池中放入一定數(shù)量的連接,當需要建立數(shù)據(jù)庫連接時,只需從“緩沖池”中取出一個,使用完畢之后再放回去
- 數(shù)據(jù)庫連接池負責分配、管理和釋放數(shù)據(jù)庫連接,它允許應用程序重復使用一個現(xiàn)有的數(shù)據(jù)庫連接,而不是重新建立一個
- 數(shù)據(jù)庫連接池在初始化時將創(chuàng)建一定數(shù)量的數(shù)據(jù)庫連接放到連接池中,這些數(shù)據(jù)庫連接的數(shù)量是由最小數(shù)據(jù)庫連接數(shù)來設定的。無論這些數(shù)據(jù)庫連接是否被使用,連接池都將一直保證至少擁有這么多的連接數(shù)量。連接池的最大數(shù)據(jù)庫連接數(shù)量限定了這個連接池能占有的最大連接數(shù),當應用程序向連接池請求的連接數(shù)超過最大連接數(shù)量時,這些請求將被加入到等待隊列中
2.1 數(shù)據(jù)庫連接池技術的優(yōu)點
- 資源重用
- 由于數(shù)據(jù)庫連接得以重用,避免了頻繁創(chuàng)建,釋放連接引起的大量性能開銷。在減少系統(tǒng)消耗的基礎上,另一方面也增加了系統(tǒng)運行環(huán)境的平穩(wěn)性。
- 更快的系統(tǒng)反應速度
- 數(shù)據(jù)庫連接池在初始化過程中,往往已經創(chuàng)建了若干數(shù)據(jù)庫連接置于連接池中備用。此時連接的初始化工作均已完成。對于業(yè)務請求處理而言,直接利用現(xiàn)有可用連接,避免了數(shù)據(jù)庫連接初始化和釋放過程的時間開銷,從而減少了系統(tǒng)的響應時間
- 新的資源分配手段
- 對于多應用共享同一數(shù)據(jù)庫的系統(tǒng)而言,可在應用層通過數(shù)據(jù)庫連接池的配置,實現(xiàn)某一應用最大可用數(shù)據(jù)庫連接數(shù)的限制,避免某一應用獨占所有的數(shù)據(jù)庫資源
- 統(tǒng)一的連接管理,避免數(shù)據(jù)庫連接泄露
- 在較為完善的數(shù)據(jù)庫連接池實現(xiàn)中,可根據(jù)預先的占用超時設定,強制回收被占用連接,從而避免了常規(guī)數(shù)據(jù)庫連接操作中可能出現(xiàn)的資源泄露
三、DRUID(德魯伊)
- 了解了數(shù)據(jù)庫連接池以及優(yōu)勢,接下來我為大家?guī)硪粋€目前常用的一個數(shù)據(jù)庫連接池框架—>德魯伊
- DRUID是阿里巴巴開源平臺上一個數(shù)據(jù)庫連接池實現(xiàn),它結合了C3P0、DBCP、PROXOOL等DB池的優(yōu)點,同時加入了日志監(jiān)控,可以很好的監(jiān)控DB池連接和SQL的執(zhí)行情況,可以說是針對監(jiān)控而生的DB連接池,據(jù)說是目前最好的連接池
3.1 德魯伊的使用
阿里德魯伊連接池技術首先分為兩步:
1.加入jar包
例如:druid-1.1.10.jar
2.代碼步驟
第一步:建立一個數(shù)據(jù)庫連接池
第二步:設置連接池的參數(shù)
第三步:獲取連接
使用德魯伊連接數(shù)據(jù)庫的方式一
//1、創(chuàng)建數(shù)據(jù)源(數(shù)據(jù)庫連接池)對象 DruidDataSource ds =new DruidDataSource(); //2、設置參數(shù) //(1)設置基本參數(shù) ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/test"); ds.setUsername("root"); ds.setPassword("mysql123"); //3、獲取連接 Connection conn = ds.getConnection(); //如果這里沒有關閉,就相當于沒有還 conn.close();
使用德魯伊連接數(shù)據(jù)庫的方式二
// 創(chuàng)建配置文件druid.properties url=jdbc:mysql://localhost:3306/0319db ?rewriteBatchedStatements=true username=root password=123456 driverClassName=com.mysql.jdbc.Driver 代碼如下: Properties pro = new Properties(); pro.load(TestDruid2.class.getClassLoader().getResourceAsStream("druid.properties")); DataSource ds= DruidDataSourceFactory.createDataSource(pro); Connection conn = ds.getConnection();
這里注意了,德魯伊配置文件中的key,必須跟我下面一樣,否則連接不成功哦
// druid.properties內容 url=jdbc:mysql://localhost:3306/demo username=root password=123321 driverClassName=com.mysql.jdbc.Driver
四、DBUtils工具類
- 既然數(shù)據(jù)庫連接有了數(shù)據(jù)庫連接池這么方便地操作,那么對數(shù)據(jù)的增刪改查有沒有相關的方法呢?當然有,它就是DBUtils
- 將常用的操作數(shù)據(jù)庫的JDBC的類和方法集合在一起,就是DBUtils.
- 這個比較簡單,我就介紹一下常用的API操作,具體的知識點,可以查看Java的API文檔
我就直接上操作了,這里還是使用我前面實現(xiàn)的那個JDBCUtils類哈,偷個懶…
package com.company.jdbc2; import com.company.jdbc.JDBCUtils; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.junit.Test; import java.sql.SQLException; import java.util.List; /* 通過使用DBUtils工具類實現(xiàn)增,刪,改,查的操作 */ public class DBUtilsDemo { @Test public void test() throws SQLException { //1.創(chuàng)建操作對象 QueryRunner queryRunner = new QueryRunner(); //2.增,刪,改是一個方法 /* update(Connection conn, String sql, Object param) conn : 連接對象 sql : sql語句 param : 給占位符賦值的內容 */ String sql = "insert into student(sid,sname,sage) values(?,?,?)"; //返回值 :有幾條數(shù)據(jù)受到影響 int i = queryRunner.update(JDBCUtils.getConnection(), sql, 10, "kongkong", 18); System.out.println("有" + i + "條數(shù)據(jù)受到影響"); } @Test public void test2() throws SQLException { QueryRunner queryRunner = new QueryRunner(); /* query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) conn : 連接對象 sql : sql語句 */ String sql = "select sid a,sname,sage from student where sid=?"; //注意:類中的屬性名一定要和字段名相同。如果不相同則需要在sql語句中使用別名 // Student student = queryRunner.query(JDBCUtils.getConnection(), sql, // new BeanHandler<Student>(Student.class), 10); sql = "select sid a,sname,sage from student"; List<Student> list = queryRunner.query(JDBCUtils.getConnection(), sql, new BeanListHandler<Student>(Student.class)); for (Student s : list) { System.out.println(s); } } }
使用批處理
當我們需要對進行大批量的數(shù)據(jù)操作時,可以采用批處理技術,很簡單,在url中添加批處理的參數(shù)
jdbc:mysql://localhost:3306/Demo?rewriteBatchedStatements=true
示例代碼,(咳咳,依舊是我那個JDBCUtils實現(xiàn)連接的工具類…)
package com.company.jdbc3; import com.company.jdbc.JDBCUtils; import org.junit.Test; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /* 批處理: */ public class BatchDemo { /* 使用批處理: 1.mysql驅動包的版本必須為5.1.3x 才支持批處理 2.在url連接中添加如下參數(shù) jdbc:mysql://localhost:3306/Demo?rewriteBatchedStatements=true 3.使用一些API: //添加到批處理中 ps.addBatch(); //執(zhí)行批處理 ps.executeBatch(); //清空批處理 ps.clearBatch(); */ @Test public void test2() throws SQLException { //1.獲取數(shù)據(jù)庫連接 Connection connection = JDBCUtils.getConnection(); //2.預編譯 PreparedStatement ps = connection.prepareStatement( "insert into student(sid,sname,sage) values(?,?,?)"); //3.給占位符賦值 for (int i = 1; i <= 100000 ; i++) { ps.setInt(1,i); ps.setString(2,"aaa"+i); ps.setInt(3,i); //添加到批處理中 ps.addBatch(); if (i % 1000 == 0){ //執(zhí)行sql ps.executeBatch();//執(zhí)行批處理 //清空批處理 ps.clearBatch(); } } //4.關資源 JDBCUtils.close(ps,connection); } @Test public void test() throws SQLException { //1.獲取數(shù)據(jù)庫連接 Connection connection = JDBCUtils.getConnection(); //2.預編譯 PreparedStatement ps = connection.prepareStatement( "insert into student(sid,sname,sage) values(?,?,?)"); //3.給占位符賦值 for (int i = 1; i <= 100000 ; i++) { ps.setInt(1,i); ps.setString(2,"aaa"+i); ps.setInt(3,i); //執(zhí)行sql ps.executeUpdate(); } //4.關資源 JDBCUtils.close(ps,connection); } }
到此這篇關于JDBC的擴展知識點總結的文章就介紹到這了,更多相關JDBC知識點內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- JDBC用法小結
- Java 數(shù)據(jù)庫連接(JDBC)的相關總結
- Java JDBC連接數(shù)據(jù)庫常見操作總結
- 使用JDBC連接Mysql數(shù)據(jù)庫會出現(xiàn)的問題總結
- JDBC連接mysql亂碼異常問題處理總結
- JDBC常用接口總結
- javaweb學習總結——使用JDBC處理MySQL大數(shù)據(jù)
- Java中JDBC事務與JTA分布式事務總結與區(qū)別
- java開發(fā)中基于JDBC連接數(shù)據(jù)庫實例總結
- JDBC連接Sql Server 2005總結
- 淺析JAVA常用JDBC連接數(shù)據(jù)庫的方法總結
- JDBC數(shù)據(jù)庫的使用操作總結
相關文章
Java中HashMap和Hashtable及HashSet的區(qū)別
以下是對Java中HashMap和Hashtable及HashSet的區(qū)別進行了詳細的分析介紹,需要的朋友可以過來參考下2013-09-09macOS中搭建Java8開發(fā)環(huán)境(基于Intel?x86?64-bit)
這篇文章主要介紹了macOS中搭建Java8開發(fā)環(huán)境(基于Intel?x86?64-bit)?的相關資料,需要的朋友可以參考下2022-12-12