Springboot有一致的事務模型
JDBC/Hibernate/myBatis
DataSource/JTA
事務抽象的核心接口
PlatformTransactionManager
DataSourceTransationManager
HibernateTransactionManager
JtaTransactionManager
TransactionDefinition
Propagation //傳播性
Isolation //隔離性
Timeout //超時
Read-only status //是否只讀
傳播性 | 值 | 描述 |
PROPAGATION_REQUIRED | 0 | 當前有事務用當前的,沒有就用新的 |
PROPAGATION_SUPPORTS | 1 | 事務可有可無,不是必須的 |
PROPAGATION_MANDATORY | 2 | 當前一定要有事務,不然就拋異常 |
PROPAGATION_REQUIRES_NEW | 3 | 無論是否有事務都起個新事務 |
PROPAGATION_NOT_SUPPORTED | 4 | 不支持事務,按非事務方式運行 |
PROPAGATION_NEVER | 5 | 不支持事務,如果有事務則拋異常 |
PROPAGATION_NESTED | 6 | 當前有事務就在當前是事務裏再起一個事務 |
隔離性 | 值 | 髒讀 | 不可重複讀 | 幻讀 |
ISOLATION_READ_UNCOMMITTER | 1 | T | T | T |
ISOLATION_READ_COMMITTED | 2 | F | T | T |
ISOLATION_REPEATABLE_READ | 3 | F | F | T |
ISOLATION_SERIALIZABLE | 4 | F | F | F |
編程式事務
TransactionTemplate
TransactionCallback
TransactionCallbackWithoutResult
PlatformTransactionManager
可以傳入TransactionDefinition進行定義
通過編程式事務編寫
package com.example.ribi;
import com.example.ribi.example.User;
import com.example.ribi.mapper.UserRepository;
import com.example.ribi.service.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootApplication
@EnableCaching(proxyTargetClass = true)
@EnableTransactionManagement
@Slf4j
public class RibiApplication implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(RibiApplication.class, args);
}
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private TransactionTemplate transactionTemplate;
@Override
public void run(ApplicationArguments args) throws Exception{
log.info("0s count is {}",getCount()); //0s 一開始表裏有的記錄
jdbcTemplate.execute("insert into user values (10,'aaa','bbb')");
log.info("1s count is {}",getCount()); //1s 插入一條記錄後
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcTemplate.execute("insert into user values (11,'aaa','bbb')");
log.info("2s count is {}",getCount()); //2s 開啓事務設置回滾,插入一條記錄再查詢
status.setRollbackOnly();
}
});
log.info("3s count is {}",getCount()); //3s 查詢事務回滾後的表記錄數
}
public Long getCount(){
return (Long)jdbcTemplate.queryForList("select count(1) as CNT from user").get(0).get("CNT");
}
}
運行結果
2019-05-21 17:57:24.745 INFO 48768 --- [main] com.example.ribi.RibiApplication : 0s count is 4 // 一開始4條
2019-05-21 17:57:24.786 INFO 48768 --- [main] com.example.ribi.RibiApplication : 1s count is 5 // 插入一條後變5條
2019-05-21 17:57:24.805 INFO 48768 --- [main] com.example.ribi.RibiApplication : 2s count is 6 // 開啓事務再插入一條查詢變成6條 然後再回滾
2019-05-21 17:57:24.820 INFO 48768 --- [main] com.example.ribi.RibiApplication : 3s count is 5 // 回滾後變成5條
註解:
Application類添加
@EnableTransactionManagement
註解在方法頭上添加
@Transactional
-- 部分摘自 極客時間 玩轉Spring全家桶