回滚不适用于多个插入
Rollback is not working for multiple insert
@Transactional 应用程序内部方法的注释 class 不会回滚插入。但是,服务 class(EmpService.java) 方法 ("insertEmp(Emp emp)") 上的 @Transactional 注释按预期工作。
有人可以告诉我为什么@Transactional 的工作方式不同吗?
Spring 引导版本 - 2.1.3.RELEASE 带有 h2 数据库。
如果需要任何其他信息,请告诉我。
@SpringBootApplication
@ComponentScan("org.saheb")
@EnableJpaRepositories("org.saheb.repo")
@EntityScan("org.saheb.vo")
@EnableTransactionManagement
public class SpringJpaTransactionApplication implements CommandLineRunner {
@Autowired
private EmpService empService;
public static void main(String[] args) {
SpringApplication.run(SpringJpaTransactionApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
insertSingleBatch();
}
@Transactional(rollbackFor=RuntimeException.class, propagation=Propagation.REQUIRES_NEW)
public void insertSingleBatch() {
try {
Set<Emp> empSet = new LinkedHashSet<>();
Dept dept = new Dept();
dept.setDeptNo(10);
empSet.add(new Emp("abc", "abc", dept));
empSet.add(new Emp("xyz", "xyz", dept));
empSet.add(new Emp("def", "def", dept));
empSet.add(new Emp("pqrstu", "pqr", dept));// This will fail as max character allowed in 5 and should rollback all the insertion. But, first three records are getting saved in h2 database.
empService.insertEmp(empSet);
} catch (RuntimeException e) {
System.out.println("Exception in batch1.." + e.getMessage());
}
}
}
@Service
public class EmpService {
@Autowired
private EmpRepository empRepository;
//@Transactional(rollbackFor=RuntimeException.class, propagation=Propagation.REQUIRES_NEW)//This is working as expected as all the insertions are rolling back after failure of 4th insertion
public void insertEmp(Set<Emp> empSet) {
System.out.println("Inside insert");
for (Emp temp : empSet) {
Emp temp2 =empRepository.save(temp);
System.out.println("inserted-->"+temp2.getFirstName());
}
}
}
您是 "self-invocation" 来自同一个 bean 的 @Transactional
方法,该方法将不起作用。此行为在 here and here 的文档中有很好的解释(搜索关键字 "self-invocation")
您可以简单地将 @Transactional
方法移动到另一个 bean.Then 将此 bean 注入其客户端 bean 并调用此 @Transactional
方法。
或者使用TransactionTemplate
在事务中执行:
@Autowired
private TransactionTemplate txTemplate;
@Override
public void run(String... args) throws Exception {
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
txTemplate.execute(status->{
insertSingleBatch();
return null;
});
}
请注意 TransactionTemplate
将忽略 @Transactional
上的设置,您必须以编程方式配置它。
@Transactional 应用程序内部方法的注释 class 不会回滚插入。但是,服务 class(EmpService.java) 方法 ("insertEmp(Emp emp)") 上的 @Transactional 注释按预期工作。
有人可以告诉我为什么@Transactional 的工作方式不同吗? Spring 引导版本 - 2.1.3.RELEASE 带有 h2 数据库。 如果需要任何其他信息,请告诉我。
@SpringBootApplication
@ComponentScan("org.saheb")
@EnableJpaRepositories("org.saheb.repo")
@EntityScan("org.saheb.vo")
@EnableTransactionManagement
public class SpringJpaTransactionApplication implements CommandLineRunner {
@Autowired
private EmpService empService;
public static void main(String[] args) {
SpringApplication.run(SpringJpaTransactionApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
insertSingleBatch();
}
@Transactional(rollbackFor=RuntimeException.class, propagation=Propagation.REQUIRES_NEW)
public void insertSingleBatch() {
try {
Set<Emp> empSet = new LinkedHashSet<>();
Dept dept = new Dept();
dept.setDeptNo(10);
empSet.add(new Emp("abc", "abc", dept));
empSet.add(new Emp("xyz", "xyz", dept));
empSet.add(new Emp("def", "def", dept));
empSet.add(new Emp("pqrstu", "pqr", dept));// This will fail as max character allowed in 5 and should rollback all the insertion. But, first three records are getting saved in h2 database.
empService.insertEmp(empSet);
} catch (RuntimeException e) {
System.out.println("Exception in batch1.." + e.getMessage());
}
}
}
@Service
public class EmpService {
@Autowired
private EmpRepository empRepository;
//@Transactional(rollbackFor=RuntimeException.class, propagation=Propagation.REQUIRES_NEW)//This is working as expected as all the insertions are rolling back after failure of 4th insertion
public void insertEmp(Set<Emp> empSet) {
System.out.println("Inside insert");
for (Emp temp : empSet) {
Emp temp2 =empRepository.save(temp);
System.out.println("inserted-->"+temp2.getFirstName());
}
}
}
您是 "self-invocation" 来自同一个 bean 的 @Transactional
方法,该方法将不起作用。此行为在 here and here 的文档中有很好的解释(搜索关键字 "self-invocation")
您可以简单地将 @Transactional
方法移动到另一个 bean.Then 将此 bean 注入其客户端 bean 并调用此 @Transactional
方法。
或者使用TransactionTemplate
在事务中执行:
@Autowired
private TransactionTemplate txTemplate;
@Override
public void run(String... args) throws Exception {
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
txTemplate.execute(status->{
insertSingleBatch();
return null;
});
}
请注意 TransactionTemplate
将忽略 @Transactional
上的设置,您必须以编程方式配置它。