Java 弹簧&x2B;Hibernate:插入多个记录和@Transactional
我有一个基于Spring+Hibernate的应用程序。我试图从文件中的条目列表将数据插入数据库。基本思想是插入所有具有有效数据的记录,并为所有尚未插入的条目记录错误报告 一个@Transactional服务类调用另一个服务类来读取文件并插入数据库。现在,我一个接一个地插入记录。也许我会改成批量处理。插入在try-catch块中执行 伪代码:Java 弹簧&x2B;Hibernate:插入多个记录和@Transactional,java,spring,hibernate,jpa,transactional,Java,Spring,Hibernate,Jpa,Transactional,我有一个基于Spring+Hibernate的应用程序。我试图从文件中的条目列表将数据插入数据库。基本思想是插入所有具有有效数据的记录,并为所有尚未插入的条目记录错误报告 一个@Transactional服务类调用另一个服务类来读取文件并插入数据库。现在,我一个接一个地插入记录。也许我会改成批量处理。插入在try-catch块中执行 伪代码: @Transactional class MainService { public void insertFromFile(File
@Transactional
class MainService {
public void insertFromFile(File inputFile) {
subServuce(toIterator(inputFile)); // toIterator(..) is just for understanding.
}
}
class SubService {
public void insert(Iterator input) {
while (input.hasNext()) {
try {
DBService.save(input.next());
} catch (Exception e) {
// Log the error and continue with next records
}
}
}
}
@Transactional
class DBService {
public void save(Data input) {
generalDao.save(input);
}
}
尝试:
class SubService {
public void insert(Iterator input) {
while (input.hasNext()) {
try {
save(input.next());
} catch (Exception e) {
// Log the error and continue with next records
}
}
}
// @Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = Exception.class)
@Transactional(propagation = Propagation.NOT_SUPPORTED, noRollbackFor = Exception.class)
public void save(Data input) {
DBService.save(input);
}
}
即使处理了异常,整个事务仍在回滚,我得到了这个错误无法提交JPA事务;嵌套异常为javax.persistence.RollbackException:标记为rollbackOnly的事务
我尝试在SubService.insert(..)
上指定@Transactional(noRollBack=Exception.class)
,但没有成功
以下是我的问题:
SubServiceDao {
// @Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(Data input) {
DBService.save(input);
}
}
class SubService {
public void insert(Iterator input) {
while (input.hasNext()) {
try {
SubServiceDao.save(input.next());
} catch (Exception e) {
// Log the error and continue with next records
}
}
}
}
从javadoc:
如果会话引发异常,则必须滚动事务
返回并丢弃会话。会话的内部状态
异常发生后,可能与数据库不一致
因此,整个事务被回滚,没有任何内容保持插入状态
在插入之前进行验证(必要时进行必要的锁定),并在失败时重试整个事务。来自javadoc:
如果会话引发异常,则必须滚动事务
返回并丢弃会话。会话的内部状态
异常发生后,可能与数据库不一致
因此,整个事务被回滚,没有任何内容保持插入状态
在插入之前进行验证(必要时进行必要的锁定),并在失败时重试整个事务。尽管捕获到异常,Spring仍然能够检测到entityManager出现了问题,在这种情况下,它将事务标记为仅回滚 这是因为
entityManager
Spring injects是一个代理,它在委托给realentityManager
之前拦截所有调用,并让它知道realentityManager
抛出了异常,即使您捕获了它
我看到的一个选项是,您可以在
DBService.save(…)
方法@Transactional(propagation=propagation.REQUIRES\u new)
上启动一个新事务。这样,如果由于无效数据而发生任何异常,则只会影响插入该行,其余的仍将继续。尽管捕捉到异常,Spring仍然能够检测到entityManager出现了问题,在这种情况下,它会将事务标记为仅回滚
这是因为entityManager
Spring injects是一个代理,它在委托给realentityManager
之前拦截所有调用,并让它知道realentityManager
抛出了异常,即使您捕获了它
我看到的一个选项是,您可以在
DBService.save(…)
方法@Transactional(propagation=propagation.REQUIRES\u new)
上启动一个新事务。这样,如果由于无效数据而发生任何异常,则只会影响插入该行,剩余的行仍将继续。Hey!DBService本身用@Transactional注释。我更新了显示DBService类的问题。无论如何,我将调用DBService的部分移动到另一个方法,并将其标记为Propagation.REQUIRES\u NEW/NOT\u SUPPORTED。不起作用。您是否尝试在dao类中的generalDao.save(input)
方法上添加Propagation.REQUIRES\u NEW
。因为您应该在与entityManager
交互的方法上添加此注释。我相信generalDao.save(input)
是与entitymanager交互的工具。其余的其他事务可以在同一事务中运行。generalDao在这里,我不能为我的特定目的更改它的实现。所以我在这里无能为力,明白了。尽管您在SubService
类中用REQUIRES\u NEW
注释了save(input)
方法,但我看到的问题是,您在while循环中直接调用了这个save
方法。如果我们直接调用一个方法,它将不会被SpringAOP代理(没有新的事务),因此它将在与调用方相同的事务中运行。作为一种快速解决方法,您可以使用-((子服务)AopContext.currentProxy()).save(input)
调用save方法,或者更好地将save(input)
方法移动到新bean中并使用此新bean调用它。很抱歉响应太晚。你最初的回答帮助我解决了这个问题。我在SubService和DBService之间添加了另一个DAO,并将persist方法移动到该类中。我用解决方案更新了我的答案。嘿!DBService本身用@Transactional注释。我更新了显示DBService类的问题。无论如何,我将调用DBService的部分移动到另一个方法,并将其标记为Propagation.REQUIRES\u NEW/NOT\u SUP