EntityManager.find()和EntityManger.getReference()之间有什么区别?

46 java jpa entitymanager

什么是区别

<T> T EntityManager.find(Class<T> entityClass, Object primaryKey) and 
<T> T EntityManager.getReference(Class<T> entityClass, Object primaryKey) 
Run Code Online (Sandbox Code Playgroud)

我认为getReference如果被管理则返回实体.并且如果它被管理则查找返回实体,否则在数据库上执行SQL以使其受管.

请确认.


上下文:从webapp我得到要删除的对象的主键(pk类型为long); 应该管理实体以删除.

EntityManager.remove(Object entity)
Run Code Online (Sandbox Code Playgroud)

将托管实体传递给entitymanager删除方法'什么是更好更正确的选项?找到还是得到参考?'

Dan*_*iel 73

正如您所知,JPA具有EntityManager的概念.在您在实体管理器中工作期间,某些对象从数据库加载,可以进行修改,然后刷新到数据库.

find()必须返回对象的初始化实例.如果它尚未加载到EntityManager中,则从数据库中检索它.

getReference()如果之前尚未在EntityManager中加载实体,则允许返回代理而不是初始化实例.在此代理中,仅初始化主键属性.可以在不命中数据库的情况下创建代理,因为已经为getReference()函数提供了唯一的初始化属性.

如果您有一个实体A引用实体B,并且您希望将A的b属性设置为B,而不必从数据库中加载B,则后者非常有用.

仅当您引用B的其他属性时,才会初始化代理.

  • 实际上,getReference返回的对象不一定是任何"代理",因为这是一个实现细节; 一些将返回"代理",而其他(支持字节码增强)将返回实际类型的对象,但延迟加载.虽然您避免使用此方法调用数据库,但是在加载字段后,您可能会在以后获得多个数据库访问 (3认同)

Eel*_*lke 8

getReference() 不检索完整对象而只检索代理,因此如果不访问对象的成员,则可以更有效.

例如,在创建要插入数据库的新对象时,可能必须引用已存储在数据库中的另一个对象.

要使JPA正确存储新对象,只需要引用对象的主键.通过使用getReference()您获得包含主键的代理,您可以节省加载整个对象的成本.


Jai*_*der 7

" 使用GlassFish 3开始Java EE 6平台 "一书,请参阅第135页中的差异:"按ID查找"

find()如果找到实体,则返回; 如果未找到,则返回空值.

MyEntity obj = em.find(MyEntity.class, id);
if(obj != null){
   // Process the object 
}
Run Code Online (Sandbox Code Playgroud)

getReference() 适用于需要托管实体实例但不访问实体主键的数据的情况.

try {
    MyEntity obj = em.getReference(MyEntity.class, id);
    // Process the object
} catch (EntityNotFoundException e) {
    // Entity Not Found
}
Run Code Online (Sandbox Code Playgroud)