gpt4 book ai didi

java - 在 Hibernate 中将实体内的实体与持久化上下文分离

转载 作者:行者123 更新时间:2023-12-01 09:00:22 25 4
gpt4 key购买 nike

Hibernate 在事务方法中保留修改后的实体,我可以通过使用 session#evict(entity) 来避免。

如果我将其从持久性上下文中分离出来,其中的实体也会被分离吗?

例如,我有这样的类(class):

@Entity
public class User extends BaseEntity{
@Column(name = "email")
private String email;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private List<Address> addresses;

// getters and setters
}

@Entity
public class Address extends BaseEntity{
@Column(name = "email")
private String email;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "USER_ID")
private User user;

// getters and setters
}

如果我分离一个用户对象,但更改其中的地址对象,该地址会在事务结束时保留吗?像这样:

User user = userDAO.getById(id);
session.evict(user);
Address address = user.getAddresses().get(0);
address.setNumber(number);
addressDAO.saveOrUpdate(address); //will this work?

最佳答案

使用 EntityManager.createQuery() 更新或删除的实体不会加载到持久性上下文中,这只发生在选择查询以及使用 find()merge() 时。

执行更新或删除查询后,您的持久性上下文实际上可能与数据库不同步,因为查询不会更新已加载到持久性上下文中的实体(您需要调用 refresh()查看更改)。

如果您加载多个用户(到持久化上下文中),然后执行 Update User set status='active' where id IN (:ids) ,那么您没有修改持久化上下文中的任何用户,您只修改了数据库。要修改用户,您必须通过调用`aUser.setStatus('active')来修改实际管理的实体,当事务提交时,JPA将根据加载时创建的副本检查所有管理实体,以及是否有任何更改将进行更新。

如果您将 5000 个对象加载到持久性中,JPA 可能需要一些时间来运行实体图,并在事务提交时检测更改。如果您没有修改任何内容,并且希望加快更改检测速度,有两种方法可以实现。使用只读查询加载实体,这告诉 JPA 它不需要保留已加载实体的副本。另一种选择是调用 EntityManager.clear() 丢弃所有托管实体。但是,如果您对性能感兴趣,最好的解决方案可能是避免将实体加载到持久性上下文中。据我了解你的问题,你需要执行 Update User set ... where id IN (:ids) 并且为此你只需要用户的 id,因此你不需要加载用户,你只需要 ids,因此你可以执行 List<Long> ids = em.createQuery("select u.id from User u where ...", Long.class).getResultList();

希望这能为您澄清问题:)

编辑:这是从 JPA 角度编写的,但对于 hibernate EntityManager 只是直接转发到 SessionImpl ,因此行为与描述完全相同,除了 find() 在 native Hibernate 中被称为 get()

关于java - 在 Hibernate 中将实体内的实体与持久化上下文分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41723318/

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