gpt4 book ai didi

jpa - 为什么对我的 JPA 实体所做的更改不会持久保存到数据库中?

转载 作者:行者123 更新时间:2023-12-04 16:52:51 25 4
gpt4 key购买 nike

在 Spring Boot 应用程序中,我有一个实体 Task状态在执行期间发生变化:

@Entity
public class Task {

public enum State {
PENDING,
RUNNING,
DONE
}

@Id @GeneratedValue
private long id;
private String name;
private State state = State.PENDING;

// Setters omitted

public void setState(State state) {
this.state = state; // THIS SHOULD BE WRITTEN TO THE DATABASE
}

public void start() {
this.setState(State.RUNNING);

// do useful stuff
try { Thread.sleep(2000); } catch(InterruptedException e) {}
this.setState(State.DONE);
}
}

如果状态改变,对象应该被保存在数据库中。我使用这个 Spring Data 接口(interface)作为存储库:
 public interface TaskRepository extends CrudRepository<Task,Long> {}

而这段代码创建和启动一个 Task :
Task t1 = new Task("Task 1");
Task persisted = taskRepository.save(t1);
persisted.start();

据我了解 persisted现在附加到持久性 session ,如果对象发生更改,则应将这些更改存储在数据库中。但这并没有发生,重新加载时状态为 PENDING。

有什么想法我在这里做错了吗?

最佳答案

tl;博士

将实例附加到持久性上下文并不意味着对象状态的每次更改都会直接持久化。更改检测仅发生在持久性上下文生命周期中的某些事件上。

细节

您似乎误解了更改检测的工作方式。 JPA 的一个非常核心的概念是所谓的持久性上下文。它基本上是 unit-of-work pattern 的实现。 .您可以通过两种方式向其中添加实体:从数据库加载它们(执行查询或发出 EntityManager.find(…))或通过主动将它们添加到持久性上下文中。这就是对 save(…) 的调用。方法有效。

这里要实现的重要一点是,“将实体添加到持久化上下文”不一定等于“存储在数据库中”。持久性提供者可以自由地推迟数据库交互,只要它认为是合理的。提供者通常这样做是为了能够对数据进行批量修改操作。然而,在很多情况下,初始 save(…) (转换为 EntityManager.persist(…) )将直接执行,例如如果您使用自动 id 增量。

也就是说,现在该实体已成为托管实体。这意味着,持久化上下文会意识到这一点,并将持久化对实体所做的更改透明,如果发生需要发生的事件。最重要的是以下两个:

  • 持久性上下文关闭 .在 Spring 环境中,持久化上下文的生命周期通常绑定(bind)到一个事务。在您的特定示例中,存储库具有默认事务(以及持久性上下文)边界。如果您需要实体围绕它进行管理,您需要扩展事务生命周期(通常通过引入具有 @Transactional 注释的服务层)。在 Web 应用程序中,我们经常看到 Open Entity Manager In View Pattern,它基本上是一个请求绑定(bind)的生命周期。
  • 持久化上下文被刷新 .这可以手动发生(通过调用 EntityManager.flush() 或透明地发生。例如,如果持久性提供程序需要发出查询,它通常会刷新持久性上下文以确保查询可以找到当前待处理的更改。假设您加载了一个用户,将他的地址更改为新位置,然后发出查询以通过地址查找用户。提供者将足够聪明,先刷新地址更改,然后再执行查询。
  • 关于jpa - 为什么对我的 JPA 实体所做的更改不会持久保存到数据库中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24788484/

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