建站公司沒(méi)前端網(wǎng)站推廣app下載
目錄
1. 事務(wù)定義
2. MySQL 中的事務(wù)使用
3. 沒(méi)有事務(wù)時(shí)的插入
4. Spring 編程式事務(wù)
5. Spring 聲明式事務(wù)
5.1? @Transactional 作用范圍
5.2??@Transactional 參數(shù)說(shuō)明
5.3??@Transactional 工作原理
1. 事務(wù)定義
比如轉(zhuǎn)賬分為兩個(gè)操作:第一步操作:A -100第二步操作:A+100
2. MySQL 中的事務(wù)使用
--開(kāi)啟事務(wù)
start transaction;
--業(yè)務(wù)執(zhí)行--提交事務(wù)
commit;--回滾事務(wù)
rollback;
3. 沒(méi)有事務(wù)時(shí)的插入
@Mapper
public interface UserMapper {// 插入數(shù)據(jù)Integer insert(User user);}
@Data
public class User {private Integer id;private String username;private String password;private String photo;private Date createtime;private Date updatetime;public User(){}public User(String username, String password) {this.username = username;this.password = password;}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper"><insert id="insert">insert into userinfo (username,password,photo)values(#{username},#{password},#{photo})
</mapper>
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public Integer insert(User user){return userMapper.insert(user);}
}
@RequestMapping("/trans")
@RestController
public class TransactionalController {@Autowiredprivate UserService userService;@RequestMapping("/addUser")public Integer addUser(String username,String password){User user = new User(username,password);return userService.insert(user);}
}
?在運(yùn)行前查看數(shù)據(jù)庫(kù)的數(shù)據(jù)如下圖所示:
?運(yùn)行以上代碼后可以看到:
此時(shí)可以看到數(shù)據(jù)成功插入:?
4. Spring 編程式事務(wù)
@Slf4j
@RequestMapping("/trans")
@RestController
public class TransactionalController {@Autowiredprivate UserService userService;// 獲取數(shù)據(jù)庫(kù)事務(wù)管理器@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;private TransactionDefinition transactionDefinition;@RequestMapping("/addUser")public Integer addUser(String username,String password){TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):" +result);// 事務(wù)回滾dataSourceTransactionManager.rollback(transaction);return result;}
}
運(yùn)行成功,返回1:?
?但是,此時(shí)可以看到數(shù)據(jù)庫(kù)中的數(shù)據(jù)并未添加:
這是因?yàn)槭聞?wù)進(jìn)行了回滾。接下來(lái)我們看一下事務(wù)的提交:
@Slf4j
@RequestMapping("/trans")
@RestController
public class TransactionalController {@Autowiredprivate UserService userService;// 獲取數(shù)據(jù)庫(kù)事務(wù)管理器@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@RequestMapping("/addUser")public Integer addUser(String username,String password){TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):" +result);// 事務(wù)回滾
// dataSourceTransactionManager.rollback(transaction);// 提交事務(wù)dataSourceTransactionManager.commit(transaction);return result;}
}
可以看到數(shù)據(jù)此時(shí)提交成功:
5. Spring 聲明式事務(wù)
@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionalController2 {@Autowiredprivate UserService userService;@Transactional@RequestMapping("/addUser")public Integer addUser(String username,String password){User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):"+result);return result;}
}
?根據(jù)打印的日志我們可以看到數(shù)據(jù)提交成功了:
那么,我們?nèi)绾巫屖聞?wù)進(jìn)行回滾呢?
手動(dòng)添加異常:
@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionalController2 {@Autowiredprivate UserService userService;@Transactional@RequestMapping("/addUser")public Integer addUser(String username,String password){User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):"+result);int a = 10/0;return result;}
}
?運(yùn)行結(jié)果:
?可以看到數(shù)據(jù)并沒(méi)有提交:
?查看日志可以發(fā)現(xiàn),此時(shí)打印的日志和事務(wù)回滾時(shí)的日志相同:
此時(shí),我們?nèi)サ糇⒔?@Transactional:
@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionalController2 {@Autowiredprivate UserService userService;// @Transactional@RequestMapping("/addUser")public Integer addUser(String username,String password){User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):"+result);int a = 10/0;return result;}
}
也就是說(shuō),在沒(méi)有注解 @Transactional 時(shí),數(shù)據(jù)是可以提交成功的;添加注解?@Transactional,當(dāng)有異常時(shí),事務(wù)會(huì)進(jìn)行回滾。
通過(guò)注解,不需要我們手動(dòng)開(kāi)啟事務(wù)和關(guān)閉事務(wù),如果程序執(zhí)行成功,自動(dòng)提交事務(wù);如果程序執(zhí)行異常,自動(dòng)回滾事務(wù)。
5.1? @Transactional 作用范圍
@Transactional 可以用來(lái)修飾方法或類:
- 修飾方法:只能應(yīng)用到 public 方法上,否則不生效
- 修飾類:表明該注解對(duì)該類中所有的 public 方法都生效
5.2??@Transactional 參數(shù)說(shuō)明
接下來(lái),我們?cè)O(shè)置在發(fā)生算數(shù)異常時(shí),不進(jìn)行回滾:
@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionalController2 {@Autowiredprivate UserService userService;@Transactional(noRollbackFor = ArithmeticException.class)@RequestMapping("/addUser")public Integer addUser(String username,String password){User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):"+result);int a = 10/0;return result;}
}
?接下來(lái)我們手動(dòng)扔出異常:
@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionalController2 {@Autowiredprivate UserService userService;/*** 指定異常回滾* @param username* @param password* @return*/@Transactional@RequestMapping("/addUser2")public Integer addUser2(String username,String password) throws Exception {User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):"+result);throwException();return result;}public void throwException() throws Exception{throw new IOException();}
}
?可以看到并沒(méi)有進(jìn)行回滾。
@Transactional 默認(rèn)只在遇到運(yùn)行時(shí)異常和Error時(shí)才會(huì)回滾,非運(yùn)行時(shí)異常不回滾,即 Exception 的子類中,除了 RuntimeException 及其子類。
顯式的指定所有異常均需回滾:
@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionalController2 {@Autowiredprivate UserService userService;/*** 指定異?;貪L* @param username* @param password* @return*/@Transactional(rollbackFor = Exception.class)// 顯式的指定所有異常均需要回滾@RequestMapping("/addUser2")public Integer addUser2(String username,String password) throws Exception {User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):"+result);throwException();return result;}public void throwException() throws Exception{throw new IOException();}
}
可以看到事務(wù)進(jìn)行了回滾:
?如果異常被捕獲,事務(wù)不會(huì)回滾:
@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionalController2 {@Autowiredprivate UserService userService;@Transactional@RequestMapping("/addUser3")public Integer addUser3(String username,String password) throws Exception {User user = new User(username,password);Integer result = userService.insert(user);log.info("影響行數(shù):"+result);try{int a = 10/0;}catch (Exception e){e.printStackTrace();}return result;}
}
可以看到事務(wù)沒(méi)有回滾,正常提交:?