文章相關視頻出處:https://developer.aliyun.com/lesson_1698_13612#_13612
一、事務四大屬性(ACID)
分別是原子性、一致性、隔離性、持久性.
1、原子性(Atomicity):事務中所有的操作是不再分割的原子單位.事務中的所有操作要麼全部執行成功,要麼全部執行失敗.
2、一致性(Consistency):事務執行後,數據庫狀態與其他業務規則保持一致.如轉賬,無論事務執行成功與否,參與轉賬的2個賬號餘額之和應該是不變的
3、隔離性(Isolation):在併發操作中,不同事物之間應該隔離開來,使每個併發中的事務不會相互干擾
4、持久性(Durability):一旦事務提交成功,事務中所有的數據操作必須被持久化到數據庫中,即使提交事務後,數據庫馬上崩潰,在數據庫重啓時,也必須能保證通過某種機制恢復數據
jdbc事務
在jdbc中處理事務,都是通過Connection完成的,同一事務中的所有操作,都在使用同一個Connection對象
1jdbc中的事務
Connection的三個方法與事務相關;
setAutoCommit(boolean);設置是否爲自動提交事務,執行一條語句就提交,設置爲false才能合理使用事務,因爲操作往往是多個操作綁定在一起.
commit();提交結束事務
rollback();回滾結束事務
jdbc處理是事務的代碼格式:
try{
con.setAutoCommit(false);//開啓事務
con.commit();提交事務
}catch(){
con.rollback();回滾事務
}
二、代碼
數據庫
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`balance` decimal(12,0) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
package jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
/**
* jdbc完成事務處理
* Created by kevin on 2020/3/25.
*/
public class Demo4 {
public void zhuanzhang(String from,String to,double money){
Connection connection = null;
try {
//Connection 同一事務中的所有操作,都在使用同一個Connection對象
connection = JdbcUtils.getConnection();
//開啓事務
connection.setAutoCommit(false);
AccountDao accountDao = new AccountDao();
accountDao.updateBalance(connection,from,-10000);
if(true){
throw new RuntimeException("失敗了");
}
accountDao.updateBalance(connection,to,+10000);
//提交事務
connection.commit();
} catch (Exception e) {
e.printStackTrace();
try {
//回滾事務
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Test
public void fun1(){
zhuanzhang("ls","zs",10000);
}
}
當拋出失敗了的異常時,2個用戶數據未出現變更和數據錯亂,體現了事務的作用
package jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
/**
* Created by kevin on 2020/3/24.
*/
public class JdbcUtils {
private static Properties properties = null;
static {
try {
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbconfig.properties");
properties = new Properties();
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws Exception{
Class.forName(properties.getProperty("driverClassName"));
return DriverManager.getConnection(properties.getProperty("url"),properties.getProperty("name"),properties.getProperty("password"));
}
}
package jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
/**
* Created by kevin on 2020/3/25.
*/
public class AccountDao {
/**
* 修改指定用戶的餘額
* @param connection
* @param name
* @param balance
*/
public void updateBalance(Connection connection,String name,double balance){
try{
String sql = "update account set balance=balance+? where name=?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setDouble(1,balance);
preparedStatement.setString(2,name);
preparedStatement.executeUpdate();
}catch (Exception e){
}
}
}
maven工程目錄預覽
Demo4中存在的問題延伸
當前所有對Connection的操作都在Service層進行處理
需要把所有對Connection操作隱藏起來