JDBC的擴(kuò)展知識點(diǎn)總結(jié)
一、數(shù)據(jù)庫的事務(wù)
1.1 事務(wù)概述
- 事務(wù):一組邏輯操作單元,使數(shù)據(jù)從一種狀態(tài)變換到另一種狀態(tài)
- 事務(wù)處理(事務(wù)操作):保證所有事務(wù)都作為一個工作單元來執(zhí)行,即使出現(xiàn)了故障,都不能改變這種執(zhí)行方式。當(dāng)在一個事務(wù)中執(zhí)行多個操作時,要么所有的事務(wù)都被提交(commit),那么這些修改就永久地保存下來;要么數(shù)據(jù)庫管理系統(tǒng)將放棄所作的所有修改,整個事務(wù)回滾(rollback)到最初狀態(tài)
- 為確保數(shù)據(jù)庫中數(shù)據(jù)的一致性,數(shù)據(jù)的操縱應(yīng)當(dāng)是離散的成組的邏輯單元:當(dāng)它全部完成時,數(shù)據(jù)的一致性可以保持,而當(dāng)這個單元中的一部分操作失敗,整個事務(wù)應(yīng)全部視為錯誤,所有從起始點(diǎn)以后的操作應(yīng)全部回退到開始狀態(tài)
- 舉個栗子,當(dāng)小明給小紅轉(zhuǎn)賬時,因?yàn)榉N種原因沒有轉(zhuǎn)賬成功,小明的錢減少了,小紅卻沒有收到錢,此時就需要事務(wù)回滾,否則小明就得哭死…
1.2 事務(wù)的屬性
事務(wù)的ACID(acid)屬性
- 原子性(Atomicity)
- 原子性是指事務(wù)是一個不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
- 一致性(Consistency)
- 事務(wù)必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另外一個一致性狀態(tài)。
- 隔離性(Isolation)
- 事務(wù)的隔離性是指一個事務(wù)的執(zhí)行不能被其他事務(wù)干擾,即一個事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對并發(fā)的其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個事務(wù)之間不能互相干擾。
- 持久性(Durability)
- 持久性是指一個事務(wù)一旦被提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的,接下來的其他操作和數(shù)據(jù)庫故障不應(yīng)該對其有任何影響
1.3 JDBC事務(wù)處理
當(dāng)一個連接對象被創(chuàng)建時,默認(rèn)情況下是自動提交事務(wù):每次執(zhí)行一個 SQL 語句時,如果執(zhí)行成功,就會向數(shù)據(jù)庫自動提交,而不能回滾
為了讓多個 SQL 語句作為一個事務(wù)執(zhí)行:
1. 調(diào)用 Connection 對象的 setAutoCommit(false); 以取消自動提交事務(wù)
2.在所有的 SQL 語句都成功執(zhí)行后,調(diào)用 commit(); 方法提交事務(wù)
3.在出現(xiàn)異常時,調(diào)用 rollback(); 方法回滾事務(wù)
4.若此時 Connection 沒有被關(guān)閉, 則需要恢復(fù)其自動提交狀態(tài)
1.4 數(shù)據(jù)庫事務(wù)使用的過程
使用數(shù)據(jù)庫的事務(wù),我們需要配合異常處理try
public void testJDBCTransaction() {
Connection conn = null;
try {
// 1.獲取數(shù)據(jù)庫連接
conn = JDBCUtils.getConnection();
// 2.開啟事務(wù)
conn.setAutoCommit(false);
// 3.進(jìn)行數(shù)據(jù)庫操作
// 4.若沒有異常,則提交事務(wù)
conn.commit();
} catch (Exception e) {
e.printStackTrace();
// 5.若有異常,則回滾事務(wù)
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}} finally {
JDBCUtils.close(null, null, conn); } }
1.5 使用數(shù)據(jù)庫事務(wù)的好處
使用COMMIT 和 ROLLBACK語句,我們可以:
- 確保數(shù)據(jù)完整性。
- 數(shù)據(jù)改變被提交之前預(yù)覽。
- 將邏輯上相關(guān)的操作分組
提交或回滾前的數(shù)據(jù)狀態(tài)
- 改變前的數(shù)據(jù)狀態(tài)是可以恢復(fù)的
- 執(zhí)行 DML 操作的用戶可以通過 SELECT 語句查詢提交或回滾之前的修正
- 其他用戶不能看到當(dāng)前用戶所做的改變,直到當(dāng)前用戶結(jié)束事務(wù)。
- DML語句所涉及到的行被鎖定, 其他用戶不能操作
提交后的數(shù)據(jù)狀態(tài)
- 數(shù)據(jù)的改變已經(jīng)被保存到數(shù)據(jù)庫中。
- 改變前的數(shù)據(jù)已經(jīng)丟失。
- 所有用戶可以看到結(jié)果。
- 鎖被釋放, 其他用戶可以操作涉及到的數(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轉(zhuǎn)賬1000
AA 2000
CC 2000
try{
開啟事務(wù)
AA -= 1000
System.out.println(1/0);
CC += 1000
提交(一旦提交數(shù)據(jù)不能再回滾(撤銷))
}catch(Exception e){
事務(wù)回滾(撤銷)
}
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語句
//預(yù)編譯
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.事務(wù)提交
connection.commit();
}catch (Exception e){
e.printStackTrace();
//5.事務(wù)回滾
connection.rollback();
}finally {
//6.允許自動提交
connection.setAutoCommit(true);
//7.關(guān)閉資源----最后關(guān)閉資源
JDBCUtils.close(ps,connection);
}
}
}
二、數(shù)據(jù)庫連接池
概述
前面我們的示例代碼中,一直在調(diào)用我寫的那個JDBCUtils類來完成數(shù)據(jù)庫的連接,如果我們在別的工程中,就需要復(fù)制一下我的那個類,并且我寫的那個也不是很嚴(yán)謹(jǐn),我前面實(shí)現(xiàn)的數(shù)據(jù)庫連接方式存在以下問題:
- 普通的JDBC數(shù)據(jù)庫連接使用 DriverManager 來獲取,每次向數(shù)據(jù)庫建立連接的時候都要將 Connection 加載到內(nèi)存中,再驗(yàn)證用戶名和密碼
- 數(shù)據(jù)庫的連接資源并沒有得到很好的重復(fù)利用.若同時有幾百人甚至幾千人在線,頻繁的進(jìn)行數(shù)據(jù)庫連接操作將占用很多的系統(tǒng)資源,嚴(yán)重的甚至?xí)斐煞?wù)器的崩潰
- 對于每一次數(shù)據(jù)庫連接,使用完后都得斷開。否則,如果程序出現(xiàn)異常而未能關(guān)閉,將會導(dǎo)致數(shù)據(jù)庫系統(tǒng)中的內(nèi)存泄漏,最終將導(dǎo)致重啟數(shù)據(jù)庫
- 這種開發(fā)不能控制被創(chuàng)建的連接對象數(shù),系統(tǒng)資源會被毫無顧及的分配出去,如連接過多,也可能導(dǎo)致內(nèi)存泄漏,服務(wù)器崩潰
使用數(shù)據(jù)庫連接池
- 數(shù)據(jù)庫連接池的基本思想就是為數(shù)據(jù)庫連接建立一個“緩沖池”。預(yù)先在緩沖池中放入一定數(shù)量的連接,當(dāng)需要建立數(shù)據(jù)庫連接時,只需從“緩沖池”中取出一個,使用完畢之后再放回去
- 數(shù)據(jù)庫連接池負(fù)責(zé)分配、管理和釋放數(shù)據(jù)庫連接,它允許應(yīng)用程序重復(fù)使用一個現(xiàn)有的數(shù)據(jù)庫連接,而不是重新建立一個
- 數(shù)據(jù)庫連接池在初始化時將創(chuàng)建一定數(shù)量的數(shù)據(jù)庫連接放到連接池中,這些數(shù)據(jù)庫連接的數(shù)量是由最小數(shù)據(jù)庫連接數(shù)來設(shè)定的。無論這些數(shù)據(jù)庫連接是否被使用,連接池都將一直保證至少擁有這么多的連接數(shù)量。連接池的最大數(shù)據(jù)庫連接數(shù)量限定了這個連接池能占有的最大連接數(shù),當(dāng)應(yīng)用程序向連接池請求的連接數(shù)超過最大連接數(shù)量時,這些請求將被加入到等待隊列中
2.1 數(shù)據(jù)庫連接池技術(shù)的優(yōu)點(diǎn)
- 資源重用
- 由于數(shù)據(jù)庫連接得以重用,避免了頻繁創(chuàng)建,釋放連接引起的大量性能開銷。在減少系統(tǒng)消耗的基礎(chǔ)上,另一方面也增加了系統(tǒng)運(yùn)行環(huán)境的平穩(wěn)性。
- 更快的系統(tǒng)反應(yīng)速度
- 數(shù)據(jù)庫連接池在初始化過程中,往往已經(jīng)創(chuàng)建了若干數(shù)據(jù)庫連接置于連接池中備用。此時連接的初始化工作均已完成。對于業(yè)務(wù)請求處理而言,直接利用現(xiàn)有可用連接,避免了數(shù)據(jù)庫連接初始化和釋放過程的時間開銷,從而減少了系統(tǒng)的響應(yīng)時間
- 新的資源分配手段
- 對于多應(yīng)用共享同一數(shù)據(jù)庫的系統(tǒng)而言,可在應(yīng)用層通過數(shù)據(jù)庫連接池的配置,實(shí)現(xiàn)某一應(yīng)用最大可用數(shù)據(jù)庫連接數(shù)的限制,避免某一應(yīng)用獨(dú)占所有的數(shù)據(jù)庫資源
- 統(tǒng)一的連接管理,避免數(shù)據(jù)庫連接泄露
- 在較為完善的數(shù)據(jù)庫連接池實(shí)現(xiàn)中,可根據(jù)預(yù)先的占用超時設(shè)定,強(qiáng)制回收被占用連接,從而避免了常規(guī)數(shù)據(jù)庫連接操作中可能出現(xiàn)的資源泄露
三、DRUID(德魯伊)
- 了解了數(shù)據(jù)庫連接池以及優(yōu)勢,接下來我為大家?guī)硪粋€目前常用的一個數(shù)據(jù)庫連接池框架—>德魯伊
- DRUID是阿里巴巴開源平臺上一個數(shù)據(jù)庫連接池實(shí)現(xiàn),它結(jié)合了C3P0、DBCP、PROXOOL等DB池的優(yōu)點(diǎn),同時加入了日志監(jiān)控,可以很好的監(jiān)控DB池連接和SQL的執(zhí)行情況,可以說是針對監(jiān)控而生的DB連接池,據(jù)說是目前最好的連接池
3.1 德魯伊的使用
阿里德魯伊連接池技術(shù)首先分為兩步:
1.加入jar包
例如:druid-1.1.10.jar
2.代碼步驟
第一步:建立一個數(shù)據(jù)庫連接池
第二步:設(shè)置連接池的參數(shù)
第三步:獲取連接
使用德魯伊連接數(shù)據(jù)庫的方式一
//1、創(chuàng)建數(shù)據(jù)源(數(shù)據(jù)庫連接池)對象
DruidDataSource ds =new DruidDataSource();
//2、設(shè)置參數(shù)
//(1)設(shè)置基本參數(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();
//如果這里沒有關(guān)閉,就相當(dāng)于沒有還
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內(nèi)容 url=jdbc:mysql://localhost:3306/demo username=root password=123321 driverClassName=com.mysql.jdbc.Driver
四、DBUtils工具類
- 既然數(shù)據(jù)庫連接有了數(shù)據(jù)庫連接池這么方便地操作,那么對數(shù)據(jù)的增刪改查有沒有相關(guān)的方法呢?當(dāng)然有,它就是DBUtils
- 將常用的操作數(shù)據(jù)庫的JDBC的類和方法集合在一起,就是DBUtils.
- 這個比較簡單,我就介紹一下常用的API操作,具體的知識點(diǎn),可以查看Java的API文檔

我就直接上操作了,這里還是使用我前面實(shí)現(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工具類實(shí)現(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 : 給占位符賦值的內(nèi)容
*/
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);
}
}
}
使用批處理
當(dāng)我們需要對進(jìn)行大批量的數(shù)據(jù)操作時,可以采用批處理技術(shù),很簡單,在url中添加批處理的參數(shù)
jdbc:mysql://localhost:3306/Demo?rewriteBatchedStatements=true
示例代碼,(咳咳,依舊是我那個JDBCUtils實(shí)現(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驅(qū)動包的版本必須為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.預(yù)編譯
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.關(guān)資源
JDBCUtils.close(ps,connection);
}
@Test
public void test() throws SQLException {
//1.獲取數(shù)據(jù)庫連接
Connection connection = JDBCUtils.getConnection();
//2.預(yù)編譯
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.關(guān)資源
JDBCUtils.close(ps,connection);
}
}
到此這篇關(guān)于JDBC的擴(kuò)展知識點(diǎn)總結(jié)的文章就介紹到這了,更多相關(guān)JDBC知識點(diǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JDBC用法小結(jié)
- Java 數(shù)據(jù)庫連接(JDBC)的相關(guān)總結(jié)
- Java JDBC連接數(shù)據(jù)庫常見操作總結(jié)
- 使用JDBC連接Mysql數(shù)據(jù)庫會出現(xiàn)的問題總結(jié)
- JDBC連接mysql亂碼異常問題處理總結(jié)
- JDBC常用接口總結(jié)
- javaweb學(xué)習(xí)總結(jié)——使用JDBC處理MySQL大數(shù)據(jù)
- Java中JDBC事務(wù)與JTA分布式事務(wù)總結(jié)與區(qū)別
- java開發(fā)中基于JDBC連接數(shù)據(jù)庫實(shí)例總結(jié)
- JDBC連接Sql Server 2005總結(jié)
- 淺析JAVA常用JDBC連接數(shù)據(jù)庫的方法總結(jié)
- JDBC數(shù)據(jù)庫的使用操作總結(jié)
相關(guān)文章
Java中HashMap和Hashtable及HashSet的區(qū)別
以下是對Java中HashMap和Hashtable及HashSet的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-09-09
macOS中搭建Java8開發(fā)環(huán)境(基于Intel?x86?64-bit)
這篇文章主要介紹了macOS中搭建Java8開發(fā)環(huán)境(基于Intel?x86?64-bit)?的相關(guān)資料,需要的朋友可以參考下2022-12-12

