gpt4 book ai didi

java - Spring + hibernate : Inserting mutliple records and @Transactional

转载 作者:行者123 更新时间:2023-11-29 03:01:00 25 4
gpt4 key购买 nike

我有一个基于 Spring+Hibernate 构建的应用程序。我正在尝试将文件中的条目列表中的数据插入数据库。基本思想是插入所有具有有效数据的记录,并为所有未插入的条目记录错误报告。

一个服务类,即@Transactional,调用另一个服务类来读取文件并插入到数据库中。此刻,我一个接一个地插入记录。也许我会把它改成批处理。插入在 try catch block 中执行。

伪代码:

@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);
}
}

即使处理了异常,整个事务都在回滚,我收到此错误 Could not commit JPA transaction;嵌套异常是 javax.persistence.RollbackException: Transaction marked as rollbackOnly

我尝试在 SubService.insert(..) 上指定 @Transactional(noRollBack = Exception.class),但没有用。

以下是我的问题:

  1. 如何告诉 Spring 不要回滚并继续处理其他记录。
  2. 插入多条记录时不回滚是好习惯吗?这不是违反原子性规则吗?
  3. 在批处理中,这个是怎么处理的?如果发生错误是全部插入还是不插入?

    解决方法:

在@Madhusudana Reddy Sunnapu 的回答的帮助下,能够解决这个问题。

使用 Propagation.REQUIRES_NEW 在 SubService 和 DBService 之间创建了一个层。问题是即使 SubService.save(..) 被注释为@Transactional,因为它属于同一个 Bean,代理不会将其视为不同的 session 。

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
}
}
}
}

最佳答案

虽然您正在捕获异常,但 Spring 仍然能够检测到 entityManager 出现了问题。在这种情况下,它将事务标记为仅回滚。

这是因为 entityManager Spring injects 是一个代理,它在委托(delegate)给真实 entityManager 之前拦截所有调用并让它知道真正的 entityManager 抛出了异常即使你捕获了它。

我看到的一个选项是您可以在 DBService.save(...) 开始新的交易方法 @Transactional(propagation=Propagation.REQUIRES_NEW) .这样,如果由于无效数据而发生任何异常,它只会影响插入该行,其余行仍将继续。

关于java - Spring + hibernate : Inserting mutliple records and @Transactional,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34962841/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com