有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在Hibernate中从持久性上下文中分离实体中的实体

Hibernate在事务方法的基础上保持修改过的实体,我可以通过使用会话#逐出(entity)来避免

如果我将其与持久性上下文分离,其中的实体也将被分离

例如,我有以下课程:

@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?

共 (1) 个答案

  1. # 1 楼答案

    使用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,所以你不需要加载用户,你只需要id,因此你可以做List<Long> ids = em.createQuery("select u.id from User u where ...", Long.class).getResultList();

    希望这能为你澄清一些事情:)

    EDIT:这是从JPA的角度编写的,但是对于hibernate EntityManager来说,它只是直接转发到SessionImpl,所以行为与描述完全一样,除了在本机hibernate中被称为find()