gpt4 book ai didi

java - 使用 JPA2/Hibernate 并发写入和读取

转载 作者:太空宇宙 更新时间:2023-11-04 08:21:07 24 4
gpt4 key购买 nike

我希望能帮助理解为什么我的应用程序无法找到实体,即使它存在于数据库中;我认为该问题与并发写入/读取有关。我正在使用 jpa2/hibernate 4 和 spring 3。

我有一个方法,它创建一个用户,然后将 id 作为 json 对象消息发送到消息队列,在该队列中进一步处理用户。当消息处理程序 (UserProcessor.class) 尝试查找用户时会出现问题(见下文)。

注册.class

@Transactional
public Response createUser(String firstName, String lastName) {
User tmpUser = new User(firstName, lastName);
User savedUser = this.em.merge(tmpUser);

this.em.flush();

if (savedUser != null) {
processUser(savedUser.getId()); // message sent to queue.
} else {
// Throw exception...
}
}

UserProcessor.class

@Transactional(rollbackFor={javax.ws.rs.WebApplicationException.class})
public void processUser(Long id) {
User user = this.em.find(User.class, id); // No user entity is found, "user" is null.
if (user == null) {
// throw exception
}
...
}

最佳答案

我认为您可能遇到并发问题。

据我了解您的代码,它是这样工作的:

注册.createUser:

  • 步骤 A1) 打开交易 (I)
  • 步骤 A2) 创建用户并将其与该交易 (I) 一起存储在数据库中
  • 步骤 A3) 将用户 ID 放入队列
  • 步骤 A4) 提交事务 (I)

    UserProcessor.processUser(长id)

  • 步骤 B1) 从队列中获取用户 ID

  • 步骤 B2) 打开交易 (II)
  • 步骤 B3) 在事务中通过 ID 加载用户 (II)
  • 步骤 B4) 做事
  • 步骤 B5) 提交事务 (II)

您知道(取决于您的事务隔离级别)只有在提交第一个事务 (I) 时,事务 (I) 中写入的数据才能在其他事务 (II) 中读取。

因此,如果 UserProcessor.processUser 在步骤 A4 中提交事务 (I) 之前尝试处理步骤 B3,它将​​不会在数据库中看到该用户。 (如果您使用更高的事务隔离级别,您甚至可能需要在 B2 之前执行步骤 A4。)

一种解决方法是交换步骤 A3 和 A4 的顺序。重要的一点:如果在其他(外部)事务的上下文中调用 Response.createUser 方法,那么它将与外部事务一起提交!

关于java - 使用 JPA2/Hibernate 并发写入和读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9523748/

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