gpt4 book ai didi

java - 何时将 EntityManager.find() 与 EntityManager.getReference() 与 JPA 一起使用

转载 作者:IT老高 更新时间:2023-10-28 11:29:31 33 4
gpt4 key购买 nike

我遇到了一种情况(我认为这很奇怪,但可能很正常),我使用 EntityManager.getReference(LObj.getClass(), LObj.getId()) 来获取数据库实体,然后通过返回的对象被持久化到另一个表中。

所以基本上流程是这样的:

class TFacade{  createT(FObj, AObj) {    T TObj = new T();    TObj.setF(FObj);    TObj.setA(AObj);    ...    EntityManager.persist(TObj);    ...    L LObj = A.getL();    FObj.setL(LObj);    FFacade.editF(FObj);  }}@TransactionAttributeType.REQUIRES_NEWclass FFacade{  editF(FObj){    L LObj = FObj.getL();    LObj = EntityManager.getReference(LObj.getClass(), LObj.getId());    ...    EntityManager.merge(FObj);    ...    FLHFacade.create(FObj, LObj);  }}@TransactionAttributeType.REQUIREDclass FLHFacade{  createFLH(FObj, LObj){    FLH FLHObj = new FLH();    FLHObj.setF(FObj);    FLHObj.setL(LObj);    ....    EntityManager.persist(FLHObj);    ...  }}

我收到以下异常“java.lang.IllegalArgumentException:未知实体:com.my.persistence.L$$EnhancerByCGLIB$$3e7987d0”

研究了一段时间后,我终于发现是因为我使用了 EntityManager.getReference() 方法,所以我得到了上述异常,因为该方法正在返回一个代理。

这让我想知道,什么时候最好使用 EntityManager.getReference() 方法而不是 EntityManager.find() 方法

EntityManager.getReference() 如果找不到正在搜索的实体,则抛出 EntityNotFoundException,这本身就很方便。 EntityManager.find() 方法仅在找不到实体时返回 null。

关于事务边界,在我看来,您需要在将新找到的实体传递给新事务之前使用 find() 方法。如果您使用 getReference() 方法,那么您可能最终会遇到与我类似的情况,但上述异常除外。

最佳答案

当我不需要访问数据库状态时,我通常使用 getReference 方法(我的意思是 getter 方法)。只是为了改变状态(我的意思是setter方法)。如您所知,getReference 返回一个代理对象,该对象使用称为自动脏检查的强大功能。假设如下

public class Person {

private String name;
private Integer age;

}


public class PersonServiceImpl implements PersonService {

public void changeAge(Integer personId, Integer newAge) {
Person person = em.getReference(Person.class, personId);

// person is a proxy
person.setAge(newAge);
}

}

如果我调用 find 方法,JPA 提供者会在后台调用

SELECT NAME, AGE FROM PERSON WHERE PERSON_ID = ?

UPDATE PERSON SET AGE = ? WHERE PERSON_ID = ?

如果我调用 getReference 方法,JPA 提供者会在后台调用

UPDATE PERSON SET AGE = ? WHERE PERSON_ID = ?

你知道为什么???

当你调用 getReference 时,你会得到一个代理对象。像这样的东西(JPA 提供者负责实现这个代理)

public class PersonProxy {

// JPA provider sets up this field when you call getReference
private Integer personId;

private String query = "UPDATE PERSON SET ";

private boolean stateChanged = false;

public void setAge(Integer newAge) {
stateChanged = true;

query += query + "AGE = " + newAge;
}

}

所以在事务提交之前,JPA 提供者将看到 stateChanged 标志以更新 OR NOT 个人实体。如果 update 语句后没有更新任何行,JPA 提供程序将根据 JPA 规范抛出 EntityNotFoundException。

问候,

关于java - 何时将 EntityManager.find() 与 EntityManager.getReference() 与 JPA 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1607532/

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