您好,欢迎来到星星旅游。
搜索
您的当前位置:首页事务(操作数据库,判断SQL语句是提交还是回滚)

事务(操作数据库,判断SQL语句是提交还是回滚)

来源:星星旅游
事务(操作数据库,判断SQL语句是提交还是回滚)

事务

要么都成功,要么都失败。

在⼀个事件中的事:从通知开启事务,到提交事务之间,任何⼀句语句有错误,则哪⼀句语句都不应该提交。

1、事务的⼏个状态

1、开启事务

2、事务提交 commit()。在做事务提交和回滚前,关键的头尾是:(1)通知开启事务,false是开启(connection.setAutoCommit(false);) (2)提交或回滚(提交写在try部分,回滚写在catch中)

3、事务回滚 rollback()。事务⼀旦提交(commit)了,就⽆法回滚(rollback)了。所以,应该在提交之前判断,如果崩了就不要提交,直接回滚。4、关闭事务转账:A:1千块B:1千块

A --> B: A(900)、B(1100)

不能出现A转给了B100块钱,A成为900,但是系统崩溃了,B还没收到100块钱,出现了A900块钱,B1000块钱的情况。

1、搭建环境,进⾏测试

1 Create TABLE account(

2 id INT PRIMARY KEY auto_increment,3 `name` VARCHAR(40),4 money FLOAT5 );

6 INSERT INTO account(`name`,money) VALUES ('A',1000);7 INSERT INTO account(`name`,money) VALUES ('B',1000);8 INSERT INTO account(`name`,money) VALUES ('C',1000);

View Code

2、项⽬构成

1、建的普通Maven项⽬(不⽤模板)

2、在java下建con.wang.utils⽂件夹,并在该⽂件夹下建两个class⽂件。

3、两个class⽂件中,⼀个是JDBC的⼯具类(JdbcUtils),公共的资源配置放在这;另⼀个是具体的操作数据库的类(Test_jdbc)

4、连接数据库的⽤户名,密码,数据库驱动和url都放在resources下的db.properties⽂件夹中。

driver = com.mysql.jdbc.Driver

url = jdbc:mysql://localhost:3306/jdbc_example?useUnicode=true&characterEncoding=utf8&useSSL=trueusername = rootpassword = 123456

View Code

5、导⼊mysql依赖。此外,为实现上⼀节提到的junit单元测试,还要导⼊junit依赖

mysql

mysql-connector-java 5.1.47

junit junit 4.12

View Code

3、写JDBC的⼯具类(JdbcUtils)

package com.wang.utils;import java.io.InputStream;import java.sql.*;

import java.util.Properties;public class JdbcUtils {

private static String driver = null; private static String url = null;

private static String username = null; private static String password = null; static { try {

InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream(\"db.properties\"); Properties properties = new Properties(); properties.load(in);

driver = properties.getProperty(\"driver\"); url = properties.getProperty(\"url\");

username = properties.getProperty(\"username\"); password = properties.getProperty(\"password\"); //驱动只⽤加载⼀次 Class.forName(driver);

} catch (Exception e) { e.printStackTrace(); } }

//获取连接

public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, username, password); }

//释放连接资源

public static void release(Connection conn, Statement st, ResultSet rs){ if(rs!=null){ try {

rs.close();

}catch (SQLException e){ e.printStackTrace(); } }

if(st!=null){ try {

st.close();

}catch (SQLException e){ e.printStackTrace(); } }

if(conn!=null){ try {

conn.close();

}catch (SQLException e){ e.printStackTrace(); } } }}

View Code

4、写具体的操作数据库的类(Test_jdbc)

—— 模拟转账,并测试失败情况下的回滚和成功情况下的事务提交

情况1:当写第4步,故意制造错误的时候,看看第3步的SQL语句,提交还是回滚

1 package com.wang.utils; 2 import org.junit.Test; 3

4 import java.sql.Connection; 5 import java.sql.DriverManager; 6 import java.sql.SQLException; 7 public class Test_jdbc { 8 @Test

9 public void test() throws Exception {10 //配置信息

11 //String driver = \"com.mysql.jdbc.Driver\";

12 String url = \"jdbc:mysql://localhost:3306/jdbc_example?useUnicode=true&characterEncoding=utf8&useSSL=true\";13 String username = \"root\";14 String password = \"123456\";15 Connection connection = null;16 try {

17 //第⼀步,加载驱动

18 Class.forName(\"com.mysql.jdbc.Driver\");19 //第⼆步,连接数据库

20 connection = DriverManager.getConnection(url, username, password);21 //第三步,通知开启事务。false是开启22 connection.setAutoCommit(false);23 //第四步,执⾏SQL语句

24 String sql = \"update account set money = money - 100 where name = 'A'\";25 connection.prepareStatement(sql).executeUpdate();26 //第五步,制造错误27 int i = 1/0;

28 //第六步,写第⼆句SQL语句。理论上,第五步出现错误,所以这⼀句应该也不执⾏,不应该提交,应该回滚29 String sql2 = \"update account set money = money + 100 where name = 'B'\";30 connection.prepareStatement(sql2).executeUpdate();31 //第七步,提交

32 connection.commit();

33 //第⼋步,若上⾯两天SQl都提交成功,则输出“提交成功”34 System.out.println(\"提交成功!\");35 } catch (Exception e) {36 try {

37 //如果try中的⽅法有错误,就⾛catch,通知数据库执⾏回滚事务38 connection.rollback();39 } catch (SQLException e1) {40 e1.printStackTrace();41 }

42 e.printStackTrace();

43 } finally {44 //释放资源

45 connection.close();46 }47 }48 }

View Code

2、当注释掉第五步,代码没有错误,则提交事务

package com.wang.utils;import org.junit.Test;import java.sql.*;

public class Test_jdbc { @Test

public void test() throws Exception { Connection connection = null; Statement st = null; ResultSet rs = null; try {

//第⼀步,连接数据库

connection = JdbcUtils.getConnection(); //第⼆步,通知开启事务。false是开启 connection.setAutoCommit(false); //第三步,执⾏SQL语句

String sql = \"update account set money = money - 100 where name = 'A'\"; connection.prepareStatement(sql).executeUpdate(); //第四步,故意制造错误 //int i = 1/0;

//第五步,写第⼆句SQL语句。

//注释掉第四步错误,第三步和第五步的sql和sql2语句都提交

String sql2 = \"update account set money = money + 100 where name = 'B'\"; connection.prepareStatement(sql2).executeUpdate(); //第六步,提交

connection.commit();

//第七步,若上⾯两条SQl都提交成功,则输出“提交成功” System.out.println(\"提交成功!\"); } catch (Exception e) { try {

//如果try中的⽅法有错误,就⾛catch,通知数据库执⾏回滚事务 connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); }

e.printStackTrace(); } finally { //释放资源

JdbcUtils.release(connection,st,rs); } }}

View Code

5、上述的关键在第3步,通知开启事务:connection.setAutoCommit(false); false是开启

若不通知开启事务,即使有错误,也不会回滚,直接就提交了。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- stra.cn 版权所有 赣ICP备2024042791号-4

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务