1.ビジネスの概念:
データが1つの状態から別の状態に遷移するときの論理操作単位のセット。
2.トランザクション処理の原則:
すべてのトランザクションが操作の単位として実行されることが保証されています。障害が発生した場合でも、この処理の原則を変更することはできません。トランザクションに関連するすべてのデータが変更されて永久にコミットされるか、すべてのトランザクションがトランザクションが実行されていない状態にロールバックされます。
3.これらの操作は、データベースの送信に影響します
(1)データベース接続が切断されると、データベース内のデータが送信されます
(2).DDL操作が完了し、データが自動的に送信され、ロールバックできません
(3).DML操作のデフォルトはcommitですが、set auto commit=falseによって自動コミットが許可されないように設定できます。
4.トランザクション送信をシミュレートします
トランザクション実行プロセス図:
トランザクションを含む一般的な更新方法
/**
* 包含事务的通行的方法实现增删改
* @param conn 从外部传入的数据库连接,意图在执行完一次DML操作时,数据库的连接不会断开,
* 确保事务不会因为连接断而出现提交的现象
* @param sql 增删改语句
* @param args 占位符?个数不一定,根据sql占位符的个数,传入对应数量object
*/
public static int update(Connection conn,String sql,Object... args){
int temp = -1;
PreparedStatement pst = null;
try{
//2.预编译sql语句
pst = conn.prepareStatement(sql);
//3.填充占位符
for (int i = 0; i < args.length; i++) {
pst.setObject(i+1,args[i]);
}
//4.执行
/*
pst.execute();如果是查询操作返回的是true
如果是更新操作返回的是false;
pst.executeUpdate();返回执行操作以后受影响的行数
*/
// pst.execute();
temp = pst.executeUpdate();
}catch (Exception e){
e.printStackTrace();
}finally {
//5.释放资源
closeResource(null,pst);
}
return temp;
}
(1)異常な状況下で100元を102から103に移す操作をシミュレートします。
public void testTransaction() throws Exception {
Connection conn = null;
//102向103转账100元
try{
conn = JDBCUtils.getConnection();
//关闭DML自动调教功能
conn.setAutoCommit(false);
String sql1 = "update user_tab set balance = balance - 100 where id = ?";
update(conn,sql1,102);
//模拟异常
System.out.println(10/0);
//103接受102转账100元
String sql2 = "update user_tab set balance = balance + 100 where id = ?";
update(conn,sql2,103);
//提交事务
conn.commit();
System.out.println("转账成功");
}catch (Exception e ){
e.printStackTrace();
//出现异常数据回滚
conn.rollback();
}finally {
//将自动提交功能设置还原为true
conn.setAutoCommit(true);
JDBCUtils.closeResource(conn,null);
}
}
転送に失敗しました
(2)異常なく転送状況をシミュレートする
public void testTransaction() throws Exception {
Connection conn = null;
//102向103转账100元
try{
conn = JDBCUtils.getConnection();
//关闭DML自动调教功能
conn.setAutoCommit(false);
String sql1 = "update user_tab set balance = balance - 100 where id = ?";
update(conn,sql1,102);
//模拟异常
// System.out.println(10/0);
//103接受102转账100元
String sql2 = "update user_tab set balance = balance + 100 where id = ?";
update(conn,sql2,103);
//提交事务
conn.commit();
System.out.println("转账成功");
}catch (Exception e ){
e.printStackTrace();
//出现异常数据回滚
conn.rollback();
}finally {
//将自动提交功能设置还原为true
conn.setAutoCommit(true);
JDBCUtils.closeResource(conn,null);
}
}
転送の成功
4.トランザクションのACIDプロパティ
(1)トランザクションの属性
1.アトミシティ:
原子性とは、トランザクションが不可分な作業単位であり、トランザクション内の操作がすべて発生するか、まったく発生しないことを意味します。
2.一貫性:
トランザクションにより、データベースが1つの一貫した状態から別の一貫した状態に移行する必要があります
3.分離:
トランザクションが同時に実行される場合、各トランザクション間のデータは相互に干渉せず、各トランザクション間のデータはまったく影響を受けません。
4.持久性:
トランザクションがコミットされると、それは永続的な変更であり、次に何も起こらないか、データベースの障害がトランザクションに影響を及ぼします。
(2)トランザクションの並行性
1.ダーティリード:
コミットされていないデータが 読み取られました。
トランザクションT1、トランザクションT2、T1はデータセグメントAを読み取り、読み取り値は1です。このとき、T2はAの値を変更し、T1はA = 2の値を読み取りますが、このとき、T2はトランザクションをキャンセルします。そして、A=1ステージにロールバックします。この時点で、T1によって読み取られたデータは無効であり、これはダーティ読み取りです。
2.繰り返し不可の読み取り:
送信されたデータのみを読み取り、最初に読み取られるものは、送信する前に、最初に読み取られるものと同じです。
トランザクションT1は初めてA=1を読み取ります。読み取り後、他のトランザクション(T2)がフィールドA(A = 2)を更新および送信しても、T1は送信前に常にA=1を読み取ります。
3.ファントムリーディング:
トランザクションT1は初めて100個のデータを読み取り、T2は3個のデータを挿入して送信します。T1が送信した後、T1はそれを再度読み取り、103個のデータを読み取ります。これはファントム読み取りです。
(3)分離レベル
1. READ UNCOMMITED(コミットされていないデータを読み取る)
2. READ COMMITED(コミットされたデータの読み取り)
3. REPEATED READ(繰り返し可能読み取り)
4. シリアル化:SERIALIZABLE(各トランザクションは順次実行されます)
(4)分離レベルを達成するための.javaコード(フレームワークを使用する必要があり、事前に基盤を築く必要があります)
package Transaction;
import UpAndSelMethod.Method;
import jdbcUtil.JDBCUtils;
import org.junit.Test;
import userBean.User;
import java.sql.Connection;
//*********卧槽,为啥我设置隔离级别为读未提交却读不出来修改了却为体骄傲的数据,麻了******************
public class Test隔离级别 {
//**************************测试事务并发问题与隔离级别的关系*********************************
//测试查询
@Test
public void testTransactionSelect() throws Exception {
Connection conn = JDBCUtils.getConnection();
//设置sql语句
String sql = "select id,name,balance from user_tab where id = ?";
//查看当前连接的的隔离级别
System.out.println(conn.getTransactionIsolation());
//设置当前连接的隔离级别为读未提交
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
System.out.println(conn.getTransactionIsolation());
User user = Method.selectinfo(User.class, sql, 103);
System.out.println(user);
}
//测试更新
@Test
public void testTransactionUpdate() throws Exception {
//获取连接
Connection conn = JDBCUtils.getConnection();
//设置自动提交为false
conn.setAutoCommit(false);
//sql
String sql = "update user_tab set balance = ? where id = ?";
//执行更新操作
Method.update(conn,sql,5000,103);
//线程睡眠15秒
Thread.sleep(15000);
//睡眠结束
System.out.println("修改完成");
}
}