JDBC實作交易提交與回滾實例
1.Connection類別中常用的方法回顧
1.1 Statement createStatement() throws SQLException;
實例建立一個Statement實例(即建立一個Statement實例(即建立一個Statement實例(即建立一個Statement實例(即建立一個Statement實例(即建立一個Statement實例(即建立一個Statement實例(即建立一個Statement實例(即建立一個Statement實例(即建立一個Statement實例》 :建立一個SQL執行物件)
1.2 PreparedStatement prepareStatement(String sql) throws SQLException;
當物件(即:建立一個預編譯執行物件) 1.3 void setAutoCommit(boolean autoCommit) throws SQLException;
設定事務的自動提交(false為關閉自動提交,true為啟動自動提交)
# 1.4AcobD1.4
# 手動提交事務 1.5 void rollback() throws SQLException;# 手動回滾交易# 手動回滾到事務
# 手動回滾交易##的經典案例:銀行轉帳案例
轉出和轉入是一個事務,如果轉出成功但是轉入失敗的會就需要進行事務回滾,否則就出出現轉出者餘額減少但是轉入者餘額沒有增加
注意:事務的提交與回滾是透過Connection提供的方法來呼叫的;本質上事務還是依賴資料庫的實作; Connection的方法實質上也是呼叫了資料庫事務機制.
2.1 不使用事務控制的轉帳業務
缺點:如果轉入成功,但是轉入失敗的話,會造成轉出者餘額減少,但是轉入者餘額不變
##
1 package cn.xiangxu.entity; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.util.Scanner; 6 7 import cn.xiangxu.tools.DBUtil; 8 9 public class Test {10 public static void main(String[] args) {11 Scanner scanner = new Scanner(System.in);12 System.out.println("请输入转出用户名:");13 String outName = scanner.nextLine();14 System.out.println("请输入需要转出的资金额度:");15 Double money = Double.parseDouble(scanner.nextLine());16 System.out.println("请输入转入用户名:");17 String inName = scanner.nextLine();18 System.out.println("转出账户为:" + outName + "转出金额为:" + money + "转入账户为:" + inName);19 20 21 Connection conn = null;22 try {23 conn = DBUtil.getConnection(); // 实例化连接对象24 25 // conn.setAutoCommit(false); // 关闭自动提交事务功能26 27 String sql = "UPDATE client "28 + "SET account = account - ? " 29 + "WHERE name = ? ";30 PreparedStatement ps = conn.prepareStatement(sql);31 ps.setDouble(1, money);32 ps.setString(2, outName);33 Integer rs = ps.executeUpdate();34 if(rs > 0) {35 System.out.println("转出成功");36 } else {37 System.out.println("转出失败");38 return; // 转出失败跳出函数,不再执行下面的语句;但是finally中的语句还是会执行的,因为就算天塌下来finally中的语句都会执行39 }40 41 System.out.println("======分割线=======");42 43 String sql_in = "UPDATE client "44 + "SET account = account + ? " 45 + "WHERE name = ? ";46 PreparedStatement ps_in = conn.prepareStatement(sql_in);47 ps_in.setDouble(1, money);48 ps_in.setString(2, inName);49 Integer judge_in = ps_in.executeUpdate();50 if(judge_in > 0) {51 System.out.println("转入成功");52 // conn.commit(); // 转出、转入都成功就提交事务53 } else {54 System.out.println("转入失败");55 // conn.rollback(); // 转出成功、转入失败就回滚事务56 }57 58 // conn.setAutoCommit(true); // 打开自动提交事务59 60 } catch (Exception e) {61 // TODO Auto-generated catch block62 e.printStackTrace();63 } finally {64 System.out.println("我是finally中的语句哟");65 try {66 DBUtil.closeConnection();67 } catch (Exception e) {68 // TODO Auto-generated catch block69 e.printStackTrace();70 }71 }72 }73 }
1 CREATE TABLE client (2 id INT (10) PRIMARY KEY,3 name VARCHAR (10),4 pwd VARCHAR (10),5 account INT (20)6 );
1 package cn.xiangxu.tools; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.sql.Connection; 6 import java.sql.SQLException; 7 import java.util.Properties; 8 9 import org.apache.commons.dbcp.BasicDataSource;10 11 public class DBUtil {12 /*13 * ThreadLocal用于线程跨方法共享数据使用14 * ThreadLocal内部有一个Map, key为需要共享数据的线程本身,value就是其需要共享的数据15 */16 private static ThreadLocal<Connection> tl; // 声明一个类似于仓库的东西17 private static BasicDataSource dataSource; // 声明一个数据库连接池对象18 19 // 静态代码块,在类加载的时候执行,而且只执行一次20 static {21 tl = new ThreadLocal<Connection>(); // 实例化仓库对象22 dataSource = new BasicDataSource(); // 实例数据库连接池对象23 24 Properties prop = new Properties(); // 创建一个Properties对象用(该对象可以用来加载配置文件中的属性列表)25 InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("config/mysql.properties"); // 读取配置文件信息26 try {27 prop.load(is); // 加载配置文件中的属性列表28 29 String driverClassName = prop.getProperty("driverClassName"); // 获取属性信息30 String url = prop.getProperty("url");31 String username = prop.getProperty("username");32 String password = prop.getProperty("password");33 Integer maxActive = Integer.parseInt(prop.getProperty("maxActive"));34 Integer maxWait = Integer.parseInt(prop.getProperty("maxWait"));35 36 dataSource.setDriverClassName(driverClassName); // 初始化数据库连接池(即:配置数据库连接池的先关参数)37 dataSource.setUrl(url);38 dataSource.setUsername(username);39 dataSource.setPassword(password);40 dataSource.setMaxActive(maxActive);41 dataSource.setMaxWait(maxWait);42 43 is.close(); // 关闭输入流,释放资源44 } catch (IOException e) {45 // TODO Auto-generated catch block46 e.printStackTrace();47 } 48 49 }50 51 /**52 * 创建连接对象(注意:静态方法可以直接通过类名来调用)53 * @return 连接对象54 * @throws Exception55 */56 public static Connection getConnection() throws Exception { 57 try {58 Connection conn = dataSource.getConnection(); // 创建连接对象(利用数据库连接池进行创建)59 tl.set(conn); // 将连接对象放到仓库中60 return conn; 61 } catch (Exception e) {62 // TODO Auto-generated catch block63 e.printStackTrace();64 throw e;65 }66 }67 68 /**69 * 关闭连接对象(注意:静态方法可以通过类名直接调用)70 * @throws Exception71 */72 public static void closeConnection() throws Exception {73 Connection conn = tl.get(); // 从仓库中取出连接对象74 tl.remove(); // 清空仓库75 if(conn != null) { // 判断连接对象是否释放资源76 try {77 conn.close();78 } catch (Exception e) {79 // TODO Auto-generated catch block80 e.printStackTrace();81 throw e;82 }83 }84 }85 86 }
#資料庫連線池的java原始碼
1 # zhe shi zhu shi , yi ban bu yong zhong wen 2 # deng hao liang bian mei you kong ge, mo wei mei you fen hao3 # hou mian bu neng you kong ge4 driverClassName=com.mysql.jdbc.Driver5 url=jdbc:mysql://localhost:3306/test6 username=root7 password=1828388 maxActive=1009 maxWait=3000
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 "> 2 <modelVersion>4.0.0</modelVersion> 3 <groupId>cn.xiangxu</groupId> 4 <artifactId>testJDBC</artifactId> 5 <version>0.0.1-SNAPSHOT</version> 6 <dependencies> 7 <dependency> 8 <groupId>mysql</groupId> 9 <artifactId>mysql-connector-java</artifactId>10 <version>5.1.37</version>11 </dependency>12 <dependency>13 <groupId>junit</groupId>14 <artifactId>junit</artifactId>15 <version>4.12</version>16 </dependency>17 <dependency>18 <groupId>commons-dbcp</groupId>19 <artifactId>commons-dbcp</artifactId>20 <version>1.4</version>21 </dependency>22 </dependencies>23 </project>
1 package cn.xiangxu.entity; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.SQLException; 6 import java.util.Scanner; 7 8 import cn.xiangxu.tools.DBUtil; 9 10 public class Test {11 public static void main(String[] args) {12 Scanner scanner = new Scanner(System.in);13 System.out.println("请输入转出用户名:");14 String outName = scanner.nextLine();15 System.out.println("请输入需要转出的资金额度:");16 Double money = Double.parseDouble(scanner.nextLine());17 System.out.println("请输入转入用户名:");18 String inName = scanner.nextLine();19 System.out.println("转出账户为:" + outName + "转出金额为:" + money + "转入账户为:" + inName);20 21 22 Connection conn = null;23 try {24 conn = DBUtil.getConnection(); // 实例化连接对象25 26 conn.setAutoCommit(false); // 关闭自动提交事务功能27 28 String sql = "UPDATE client "29 + "SET account = account - ? " 30 + "WHERE name = ? ";31 PreparedStatement ps = conn.prepareStatement(sql);32 ps.setDouble(1, money);33 ps.setString(2, outName);34 Integer rs = ps.executeUpdate();35 if(rs > 0) {36 System.out.println("转出成功");37 } else {38 System.out.println("转出失败");39 return; // 转出失败跳出函数,不再执行下面的语句;但是finally中的语句还是会执行的,因为就算天塌下来finally中的语句都会执行40 }41 42 System.out.println("======分割线=======");43 44 String sql_in = "UPDATE client "45 + "SET account = account + ? " 46 + "WHERE name = ? ";47 PreparedStatement ps_in = conn.prepareStatement(sql_in);48 ps_in.setDouble(1, money);49 ps_in.setString(2, inName);50 Integer judge_in = ps_in.executeUpdate();51 if(judge_in > 0) {52 System.out.println("转入成功");53 conn.commit(); // 转出、转入都成功就提交事务54 } else {55 System.out.println("转入失败");56 conn.rollback(); // 转出成功、转入失败就回滚事务57 }58 59 conn.setAutoCommit(true); // 打开自动提交事务60 61 } catch (Exception e) {62 // TODO Auto-generated catch block63 try {64 conn.rollback(); // 捕获到异常后也需要进行事务回滚65 } catch (SQLException e1) {66 // TODO Auto-generated catch block67 e1.printStackTrace();68 } 69 e.printStackTrace();70 } finally {71 System.out.println("我是finally中的语句哟");72 try {73 DBUtil.closeConnection();74 } catch (Exception e) {75 // TODO Auto-generated catch block76 e.printStackTrace();77 }78 }79 }80 }
1 package cn.xiangxu.tools; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.sql.Connection; 6 import java.sql.SQLException; 7 import java.util.Properties; 8 9 import org.apache.commons.dbcp.BasicDataSource; 10 11 public class DBUtil { 12 /* 13 * ThreadLocal用于线程跨方法共享数据使用 14 * ThreadLocal内部有一个Map, key为需要共享数据的线程本身,value就是其需要共享的数据 15 */ 16 private static ThreadLocal<Connection> tl; // 声明一个类似于仓库的东西 17 private static BasicDataSource dataSource; // 声明一个数据库连接池对象 18 19 // 静态代码块,在类加载的时候执行,而且只执行一次 20 static { 21 tl = new ThreadLocal<Connection>(); // 实例化仓库对象 22 dataSource = new BasicDataSource(); // 实例数据库连接池对象 23 24 Properties prop = new Properties(); // 创建一个Properties对象用(该对象可以用来加载配置文件中的属性列表) 25 InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("config/mysql.properties"); // 读取配置文件信息 26 try { 27 prop.load(is); // 加载配置文件中的属性列表 28 29 String driverClassName = prop.getProperty("driverClassName"); // 获取属性信息 30 String url = prop.getProperty("url"); 31 String username = prop.getProperty("username"); 32 String password = prop.getProperty("password"); 33 Integer maxActive = Integer.parseInt(prop.getProperty("maxActive")); 34 Integer maxWait = Integer.parseInt(prop.getProperty("maxWait")); 35 36 dataSource.setDriverClassName(driverClassName); // 初始化数据库连接池(即:配置数据库连接池的先关参数) 37 dataSource.setUrl(url); 38 dataSource.setUsername(username); 39 dataSource.setPassword(password); 40 dataSource.setMaxActive(maxActive); 41 dataSource.setMaxWait(maxWait); 42 43 is.close(); // 关闭输入流,释放资源 44 } catch (IOException e) { 45 // TODO Auto-generated catch block 46 e.printStackTrace(); 47 } 48 49 } 50 51 /** 52 * 创建连接对象(注意:静态方法可以直接通过类名来调用) 53 * @return 连接对象 54 * @throws Exception 55 */ 56 public static Connection getConnection() throws Exception { 57 try { 58 Connection conn = dataSource.getConnection(); // 创建连接对象(利用数据库连接池进行创建) 59 tl.set(conn); // 将连接对象放到仓库中 60 return conn; 61 } catch (Exception e) { 62 // TODO Auto-generated catch block 63 e.printStackTrace(); 64 throw e; 65 } 66 } 67 68 /** 69 * 关闭连接对象(注意:静态方法可以通过类名直接调用) 70 * @throws Exception 71 */ 72 public static void closeConnection() throws Exception { 73 Connection conn = tl.get(); // 从仓库中取出连接对象 74 tl.remove(); // 清空仓库 75 if(conn != null) { // 判断连接对象是否释放资源 76 try { 77 conn.close(); 78 } catch (Exception e) { 79 // TODO Auto-generated catch block 80 e.printStackTrace(); 81 throw e; 82 } 83 } 84 } 85 86 /** 87 * 在执行SQL语句前关闭JDBC的自动提交事务功能 88 * @throws SQLException 89 */ 90 public static void tansBegin() throws SQLException { 91 try { 92 tl.get().setAutoCommit(false); // 从仓库中获取连接对象并调用setAutoCommit来关闭自动提交事务功能 93 } catch(SQLException e) { 94 e.printStackTrace(); 95 throw e; 96 } 97 } 98 99 /**100 * 手动回滚功能101 * @throws SQLException102 */103 public static void transBack() throws SQLException {104 tl.get().rollback(); // 从仓库中获取连接对象并调用rollback来实现事务回滚操作105 tl.get().setAutoCommit(true); // 回滚启动事务自动提交功能106 }107 108 /**109 * 手动提交功能110 * @throws SQLException111 */112 public static void transCommit() throws SQLException {113 tl.get().commit(); // 从仓库中获取连接对象并调用commit来实现事务提交操作114 tl.get().setAutoCommit(true); // 提交后启动事务自动提交功能115 }116 117 }
1 package cn.xiangxu.entity; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.SQLException; 6 import java.util.Scanner; 7 8 import cn.xiangxu.tools.DBUtil; 9 10 public class Test {11 public static void main(String[] args) {12 Scanner scanner = new Scanner(System.in);13 System.out.println("请输入转出用户名:");14 String outName = scanner.nextLine();15 System.out.println("请输入需要转出的资金额度:");16 Double money = Double.parseDouble(scanner.nextLine());17 System.out.println("请输入转入用户名:");18 String inName = scanner.nextLine();19 System.out.println("转出账户为:" + outName + "转出金额为:" + money + "转入账户为:" + inName);20 21 22 Connection conn = null;23 try {24 conn = DBUtil.getConnection(); // 实例化连接对象25 26 DBUtil.tansBegin(); // 关闭自动提交事务功能27 28 String sql = "UPDATE client "29 + "SET account = account - ? " 30 + "WHERE name = ? ";31 PreparedStatement ps = conn.prepareStatement(sql);32 ps.setDouble(1, money);33 ps.setString(2, outName);34 Integer rs = ps.executeUpdate();35 if(rs > 0) {36 System.out.println("转出成功");37 } else {38 System.out.println("转出失败");39 return; // 转出失败跳出函数,不再执行下面的语句;但是finally中的语句还是会执行的,因为就算天塌下来finally中的语句都会执行40 }41 42 System.out.println("======分割线=======");43 44 String sql_in = "UPDATE client "45 + "SET account = account + ? " 46 + "WHERE name = ? ";47 PreparedStatement ps_in = conn.prepareStatement(sql_in);48 ps_in.setDouble(1, money);49 ps_in.setString(2, inName);50 Integer judge_in = ps_in.executeUpdate();51 if(judge_in > 0) {52 System.out.println("转入成功");53 DBUtil.transCommit(); // 转出、转入都成功就提交事务54 } else {55 System.out.println("转入失败");56 DBUtil.transBack(); // 转出成功、转入失败就回滚事务57 }58 59 } catch (Exception e) {60 // TODO Auto-generated catch block61 try {62 DBUtil.transBack();// 捕获到异常后也需要进行事务回滚63 } catch (SQLException e1) {64 // TODO Auto-generated catch block65 e1.printStackTrace();66 } 67 e.printStackTrace();68 } finally {69 System.out.println("我是finally中的语句哟");70 try {71 DBUtil.closeConnection();72 } catch (Exception e) {73 // TODO Auto-generated catch block74 e.printStackTrace();75 }76 }77 }78 }
以上是JDBC實作交易提交與回滾實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Java8-291之後,禁用了TLS1.1,使JDBC無法用SSL連接SqlServer2008怎麼辦,以下是解決辦法修改java.security檔案1.找到jre的java.security檔案如果是jre,在{JAVA_HOME}/jre/ lib/security中,例如????C:\ProgramFiles\Java\jre1.8.0_301\lib\security如果是Eclipse綠色免安裝便攜版在安裝資料夾搜尋java.security,例如?????xxx\plugins \org

Lockwaittimeoutexceeded;tryrestartingtransaction-如何解決MySQL報錯:事務等待逾時在使用MySQL資料庫時,有時可能會遇到一個常見的錯誤:Lockwaittimeoutexceeded;tryrestartingtransaction,該錯誤表示事務等待逾時。這個錯誤通常發生在並且

MySQL事務處理:自動提交與手動提交的差異在MySQL資料庫中,事務是一組SQL語句的集合,要麼全部執行成功,要麼全部執行失敗,保證了資料的一致性和完整性。在MySQL中,事務可以分為自動提交和手動提交,其區別在於事務提交的時機以及對事務的控制範圍。以下將詳細介紹自動提交和手動提交的區別,並給出具體的程式碼範例來說明。一、自動提交在MySQL中,如果沒有顯示

1.PDO簡介PDO是PHP的擴充庫,它提供了一個物件導向的方式來操作資料庫。 PDO支援多種資料庫,包括Mysql、postgresql、oracle、SQLServer等。 PDO使開發人員能夠使用統一的api來操作不同的資料庫,這使得開發人員可以在不同的資料庫之間輕鬆切換。 2.PDO連接資料庫要使用PDO連接資料庫,首先需要建立一個PDO物件。 PDO物件的建構函式接收三個參數:資料庫類型、主機名稱、資料庫使用者名稱和密碼。例如,以下程式碼建立了一個連接到mysql資料庫的物件:$dsn="mysq

MongoDB技術開發中遇到的事務管理問題解決方案分析隨著現代應用程式變得越來越複雜和龐大,對資料的事務處理需求也越來越高。作為一種流行的NoSQL資料庫,MongoDB在資料管理方面有著出色的效能和擴展性。然而,MongoDB在資料一致性和事務管理方面相對較弱,為開發人員帶來了挑戰。在本文中,我們將探討在MongoDB開發中遇到的事務管理問題,並提出一些解

一、資料庫程式設計的必備條件程式語言,如Java,C、C++、Python等資料庫,如Oracle,MySQL,SQLServer等資料庫驅動套件:不同的資料庫,對應不同的程式語言提供了不同的資料庫驅動包,如:MySQL提供了Java的驅動包mysql-connector-java,需要基於Java操作MySQL即需要該驅動包。同樣的,要基於Java操作Oracle資料庫則需要Oracle的資料庫驅動包ojdbc。二、Java的資料庫程式設計:JDBCJDBC,即JavaDatabaseConnectiv

MySQL事務的原理及應用場景在資料庫系統中,事務是一組SQL操作的集合,這些操作要麼全部成功執行,要麼全部失敗回滾。 MySQL作為一種常用的關聯式資料庫管理系統,支援事務的特性,能夠確保資料庫中的資料在一致性、隔離性、持久性和原子性方面得到保證。本文將從MySQL事務的基本原理入手,介紹其應用場景,並提供具體的程式碼範例供讀者參考。 MySQL事務的原理:My

一、說明在JDBC中,executeBatch這個方法可以將多個dml語句批次執行,效率比單一執行executeUpdate高很多,這是什麼原理呢?在mysql和oracle中又是如何實現批次執行的呢?本文將為大家介紹背後的原理。二、實驗介紹本實驗將透過以下三步驟進行a.記錄jdbc在mysql中批量執行和單條執行的耗時b.記錄jdbc在oracle中批量執行和單條執行的耗時c.記錄oracleplsql批量執行和單條執行的耗時相關java和資料庫版本如下:Java17,Mysql8,Oracl
