我有办法:
@Transactional
public void importChargesRequest() {
...
for (Charge charge : charges) {
try {
Charge savedCharge = saveCharge(charge);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Charge saveCharge(Charge charge) {
return chargesRepository.saveAndFlush(charge);
}
Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit
@Service
public class TestService {
private final TestDao testDao;
public TestService(TestDao testDao) {
this.testDao = testDao;
}
@Transactional
public void saveTest() {
for (int i = 0; i < 100; i++) {
Test test = new Test();
if (i == 10 || i == 20) {
test.setName("123");
} else {
test.setName(UUID.randomUUID().toString());
}
testDao.save(test);
}
}
}
和每个内部事务的另一个bean:
@Slf4j
@Component
@Repository
public class TestDao {
@PersistenceContext
private EntityManager entityManager;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(Test test) {
entityManager.persist(test);
}
}
当我第一次尝试保存时,我有20行DB。每次下一次保存,我得到+10行。名称具有约束。当我得到错误时,事务是提交而不是继续。每次保存后我都会等待98行。
如果SaveCharge
是与ImportChargesRequest
相同bean中的方法,则忽略@Transactional
注释,并且saveAndFlush在相同(外部)事务中工作。(我敢肯定,当您使用代理/拦截器来管理事务时,情况就是如此。我敢肯定,当使用基于AspectJ的事务拦截时,情况也是如此)。
通常,只有当异常一直冒泡到外部方法(标记@transaction的方法)时,事务才会被标记为回滚,但我怀疑存储库或事务管理器本身(hibernate会话)由于违反约束而直接将事务标记为回滚。
解决方案是将saveCharge移动到另一个bean,并使用importChargesRequest-method将该bean注入到该bean中。
@Service
public class ChargesDataService{
@Autowire
private ChargesRepository chargesRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Charge saveCharge(Charge charge) {
return chargesRepository.saveAndFlush(charge);
}
}
@RestController
html" target="_blank">public class ChargesController{
@Autowire
private ChargesDataService chargesDataService;
@Transactional
public void importChargesRequest() {
for (Charge charge : charges) {
try {
Charge savedCharge = chargesDataService.saveCharge(charge);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
}
补遗:注释被忽略,因为您不再通过bean实例的代理,这意味着没有拦截器被调用,这意味着没有地方处理新事务。您可以通过在saveCharge
方法中设置断点并查看StackTrace^来检查是否存在这种情况。寻找类似事务拦截器invokeWithIntransaction的方法。
^您还可以创建一个新异常,调用fillInStacktrace,然后记录/打印异常(包括其StackTrace)。
您能否帮助解决Resin+Oracle上XA事务的问题: 我们有WebApp,它必须执行涉及Oracle11.2.0.1和EHCache2.7的业务事务。(实际上可能有各种组合--两个不同的Oracle数据源(不同的模式),带有/不带有Ehcache,等等)。这就是从普通JDBC使用切换到JTA事务划分的原因。 > 在外部事务中使用Ehcache访问,在内部事务中只使用DB访问,即使在内部事务中使
我使用的是Spring3.0.5和Hibernate3.6。在我的项目中,有一个场景,我必须回滚在抛出的任何异常或错误发生的事务。这是示例代码,除了当我抛出异常时事务不会回滚之外,一切都很好,但是如果抛出任何异常,比如mysql.IntegrityConstraintException,那么事务会回滚,为什么在我的情况下没有发生这种情况? hibernate.cfg 因此,正如我所说,我的问题是,
我正在尝试使用Hibernate保存数据。一切都发生在同一会话中。逻辑如下: 1)开始交易并尝试保存: 2) 如果新记录违反完整性约束,请在外包装方法中捕获异常,打开另一个事务并查询更多数据 问题是当第二个事务执行时query.list它会抛出一个应该与前一个事务链接的异常。 SQLIntegrityConstraintViolationException:ORA-00001:唯一约束 我应该从另
我在tomcat服务器中使用具有多个数据源配置的JTA原子事务。有时我会遇到以下异常: JTA事务意外回滚(可能是由于超时);嵌套的异常是javax。交易回滚异常:事务被设置为仅回滚 出现这种异常的原因是什么?
我有Spring > 不应该失败主事务,在我的例子中是cteateSmth() 如果失败,应该回滚它自己的事务 service1.cteatsmth(); 在上面的例子中,即使尝试对cretePartA()进行捕获包装,整个cteateSmth()事务也将回滚。 我尝试使用REQUIRES_NEW来实现这一点,但在这种情况下似乎无法回滚cretePartA()操作。 我试图不为cretePartA
非常感谢