Java 1) 使用@Transactional获取其他线程的提交值,2)回滚4个不同服务的所有异常事务
我有两个彼此相关的问题。我使用的是SpringBootJPA 问题-1 我必须提交4个不同的服务。我从控制器级别一个接一个地调用这些服务。任何服务上的失败都必须回滚其他已提交的事务。 例如。, 如果控制器方法调用线程1和, i) 服务1事务成功 ii)服务2交易成功 iii)如果服务3事务失败-则服务1和服务2事务必须回滚 问题2 我正在更新服务-1上的唯一列值。首先读取实体,获取最后一行的值,增加它的值,然后再次保存。 但当另一个线程调用相同的进程时,它会读取以前读取的相同实体,并且重复值会发生错误。 例如 线程1呼叫服务1 1) 读取线程1的实体 2) 获取值,比方说-100 3) 增值至-101 4) 保存实体 5) 现在其他线程调用相同的服务 线程2呼叫服务1 1) 读取线程2的实体 2) 获取值是-100,而不是101 它给出了错误,因为在保存线程1的实体后,它应该读取更新的值,即线程2的101。但目前,我得到了未提交的值 我在这里上传实体、控制器、服务和存储库级别的代码Java 1) 使用@Transactional获取其他线程的提交值,2)回滚4个不同服务的所有异常事务,java,postgresql,spring-boot,spring-data-jpa,spring-transactions,Java,Postgresql,Spring Boot,Spring Data Jpa,Spring Transactions,我有两个彼此相关的问题。我使用的是SpringBootJPA 问题-1 我必须提交4个不同的服务。我从控制器级别一个接一个地调用这些服务。任何服务上的失败都必须回滚其他已提交的事务。 例如。, 如果控制器方法调用线程1和, i) 服务1事务成功 ii)服务2交易成功 iii)如果服务3事务失败-则服务1和服务2事务必须回滚 问题2 我正在更新服务-1上的唯一列值。首先读取实体,获取最后一行的值,增加它的值,然后再次保存。 但当另一个线程调用相同的进程时,它会读取以前读取的相同实体,并且重复值会发
//Entity Level
@Entity
@Data
public class MyEntity {
private Long id;
@Column(unique = true)
private Long uniqueCode;
}
@Entity
@Data
public class MyOtherEntity{
private Long id;
}
//Repository Level
@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
MyEntity findFirstByOrderByIdDesc();
}
@Repository
public interface MyOtherEntityRepository extends JpaRepository<MyOtherEntity, Long> {
}
//Controller Level
@Controller
public class MyController {
@Autowired
private MyService myService;
@PostMapping("/updateData")
@ResponseBody
public String updateData(){
myService.updateDataForEntity();
myService.updateDataForOtherEntity();
myService.myThirdServiceCall();
myService.myFourthServiceCall();
return "success";
}
}
//Service Level
@Service
public class MyService{
@Autowired
MyEntityRepository myEntityRepository;
@Autowired
MyOtherEntityRepository myOtherEntityRepository;
@Synchronized // Using to prevent other thread call, however error occurs
@Transactional // I have used previously (isolation = Isolation.SERIALIZABLE), but not get any result
public void updateDataForEntity() {
try {
//Get last unique code value - HERE I GOT SAME VALUE FOR OTHER THREAD (T-2) THOUGH THREAD-1 WAS SAVED
MyEntity oldEntity = myEntityRepository.findFirstByOrderByIdDesc();
//Set updated unique code value and save
MyEntity newEntity = new MyEntity();
newEntity.setUniqueCode(oldEntity.getUniqueCode() + 1L);
myEntityRepository.save(newEntity);
} catch (Exception e) {
//Should Rollback
}
}
public void updateDataForOtherEntity() {
try {
MyOtherEntity myOtherEntity = new MyOtherEntity();
myOtherEntityRepository.save(myOtherEntity);
} catch (Exception e) {
//Must rollback on exception for Service-1
}
}
public void myThirdServiceCall() {
try {
} catch (Exception e) {
// Must rollback on exception for Service-2 and service-1 call
}
}
public void myFourthServiceCall() {
try {
} catch (Exception e) {
// Must rollback on exception for Third Service Call, Service-2 and service-1 call
}
}
}
//实体级
@实体
@资料
公共类MyEntity{
私人长id;
@列(唯一=真)
专用长唯一码;
}
@实体
@资料
公共类实体{
私人长id;
}
//存储库级别
@存储库
公共接口MyEntityRepository扩展了JpaRepository{
MyEntity findFirstByOrderByIdDesc();
}
@存储库
公共接口MyOtherEntityRepository扩展了JpaRepository{
}
//控制器级
@控制器
公共类MyController{
@自动连线
私人MyService-MyService;
@后映射(“/updateData”)
@应答器
公共字符串updateData(){
myService.updateDataForEntity();
myService.updateDataForOtherEntity();
myService.myThirdServiceCall();
myService.myFourthServiceCall();
返回“成功”;
}
}
//服务水平
@服务
公共类MyService{
@自动连线
髓质沉积性髓质沉积性;
@自动连线
肌红蛋白沉积;肌红蛋白沉积;
@已同步//用于防止其他线程调用,但发生错误
@事务//我以前使用过(隔离=隔离.SERIALIZABLE),但没有得到任何结果
public void updateDataForEntity(){
试一试{
//获取最后一个唯一的代码值-在这里,我为其他线程(T-2)获取了相同的值,尽管保存了线程1
MyEntity oldEntity=myEntityRepository.findFirstByOrderByIdDesc();
//设置更新后的唯一代码值并保存
MyEntity newEntity=新MyEntity();
newEntity.setUniqueCode(oldEntity.getUniqueCode()+1L);
myEntityRepository.save(新实体);
}捕获(例外e){
//应该回滚
}
}
public void updateDataForOtherEntity(){
试一试{
MyOtherEntity MyOtherEntity=新的MyOtherEntity();
myOtherEntityRepository.save(myOtherEntity);
}捕获(例外e){
//必须在服务-1发生异常时回滚
}
}
公共无效myThirdServiceCall(){
试一试{
}捕获(例外e){
//必须回滚服务2和服务1调用的异常
}
}
public void myFourthServiceCall(){
试一试{
}捕获(例外e){
//必须在第三个服务调用、服务2和服务1调用发生异常时回滚
}
}
}
我已经阅读了有关事务传播级别和隔离级别的教程。但请指导我,我可以使用@Transactional的哪种方法来解决上述两个问题