gpt4 book ai didi

java - 不同的 REST 方法修改同一个对象 - RollbackException、OptimisticLockException、StaleStateException

转载 作者:行者123 更新时间:2023-12-02 13:16:20 29 4
gpt4 key购买 nike

我使用 Java 8、Hibernate 5.1.0.Final、Guice 4.1.0、Jersey 1.19。我有几个 REST 方法,它们可能会修改从数据库加载的同一对象 - 实体。当它们同时运行并修改同一项目时,我得到:

javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)

Caused by: javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

可能的解决方案:

还有其他选择吗?处理这个问题的最佳方法是什么?

更新1

我尝试过重试:

public void changeItemName(Long id, String name){

Item item = itemDAO.find(id);
item.setName(name);

try {
itemDAO.save(item);
} catch (RollbackException | OptimisticLockException | StaleStateException e) {
logger.warn("Retry method after " + e.getClass().getName());
changeItemName(id, name);
}
}

但我得到:

javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)

Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not update: [com.example.Item#1]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)

Caused by: org.hibernate.exception.GenericJDBCException: could not update: [com.example.Item#1]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)

Caused by: org.postgresql.util.PSQLException: This statement has been closed.
at org.postgresql.jdbc2.AbstractJdbc2Statement.checkClosed(AbstractJdbc2Statement.java:2653)

最佳答案

  1. REST 方法中的对象同步 我想说这是不可能的。想象一下在 2 个节点上运行相同的服务。

  2. 再次不断刷新对象状态不是一个选项。更新可能发生在两次刷新之间。

  3. 这个很好。 CAS原理。虽然版本不正确,但尝试保存更改。但实际上这取决于你的业务逻辑。例如。有一个 User 对象,初始名称为“name1”。第一次调用将其从“name1”更改为“name2”。第二个调用尝试从“name1”更改为“name3”。我们可以 (A) 更改名称以抑制“name1”->“name2”更新,或者 (B) 拒绝向调用者报告更改以刷新以查看实际状态并将更改应用于实际状态。

    <

如果我们尝试修改例如帐户余额 (A) 方法无效,我们需要 (B)。

您应该根据您需要的业务逻辑来决定做什么。

更新:这样是行不通的。您需要捕获它更高的位置 - 事务开始的位置并在单独的事务中执行。

假设你有

@Service
public class MyServiceImpl
@Transactional
public void changeItemName(Long id, String name) {
}

可能发生乐观锁异常的地方。如果您仅从 catch block 调用该方法,则不会启动新事务,因为没有调用代理方法。

相反,你可以做这样的事情

@Service
public class MyServiceImpl
@Autowired
private MyService myService;
@Transactional
public void changeItemName(Long id, String name) {
catch() {
myService.changeItemName(id, name);
}
}

关于java - 不同的 REST 方法修改同一个对象 - RollbackException、OptimisticLockException、StaleStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43754583/

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