49

Whats is the difference between

<T> T EntityManager.find(Class<T> entityClass, Object primaryKey) and 
<T> T EntityManager.getReference(Class<T> entityClass, Object primaryKey) 

?

I think getReference returns entity if it is managed. and find returns entity if it is managed else executes SQL on database to make it managed.

Please confirm.


Context: From webapp I get primary key of object to be deleted (pk of type long); to entity should be managed to delete.

EntityManager.remove(Object entity)

to pass managed entity to entitymanager remove method 'whats the better and correct option? find or getReference?'

  • The class names a different ... and one of them has something to do with feeding entities to livestock :-) – Stephen C Mar 30 '11 at 05:16
  • 3
    possible duplicate of [When to use EntityManager.find() vs EntityManager.getReference()](http://stackoverflow.com/questions/1607532/when-to-use-entitymanager-find-vs-entitymanager-getreference) – jmj Mar 30 '11 at 05:17

3 Answers3

82

JPA has the concept of an EntityManager, as you know. During your work in the entity manager some objects are loaded from the database, can be modified and afterwards flushed to the database.

find() has to return an initialized instance of your object. If it is not already loaded in the EntityManager, it is retrieved from the database.

getReference() is allowed to return a proxy instead of an initialized instance, if the entity has not been loaded in the EntityManager before. In this proxy, only the primary key attribute is initialized. Proxies can be created without hitting the database, because the only initialized attribute is already given to the getReference() function.

The latter is useful when you have an entity A referencing an entity B, and you want to set the b-attribute of A to B, without having to load B from the database.

Only if you reference other attributes of B, the proxy will be initialized.

Daniel
  • 27,718
  • 20
  • 89
  • 133
  • exellent explaination. thank you Daniel. if entity is already loaded there is no difference right? –  Mar 30 '11 at 06:11
  • 4
    Actually the object returned by getReference isn't necessarily any "proxy" since that is an implementation detail; some will return a "proxy" and others (that support bytecode enhancement) will return an object of the real type but lazily-loaded. While you avoid a database hit on call of this method, you then get potentially multiple database accesses later when fields are loaded – DataNucleus Mar 30 '11 at 06:30
  • One caveat to be aware of ahead of time: Combining getReference() with inheritance can cause 'instanceof' to behave in expected ways. There are ways around this, mostly around using a visitor pattern, discussed here: http://stackoverflow.com/questions/3540489/jpa-inheritance-entitymanager-find-produces-classcastexception – idle Mar 31 '11 at 00:28
  • @Daniel what happens if there is a Version annotation in the entity called by getReference? – David Hofmann Mar 25 '16 at 13:27
  • Nothing special AFAIK, we also use the @Version. And the version is not relevant, because it is not part of the key. It is just used when the entity in question is saved. – Daniel Mar 27 '16 at 11:58
  • Upvoted for "Proxies can be created without hitting the database". – Ataur Rahman Munna Sep 19 '17 at 07:24
  • @Daniel, If proxies can be created without hitting database, then why we get `EntityNotFoundException` when `getReference()` called if provided pk_id doesn't matches to any entity. – Ataur Rahman Munna Sep 19 '17 at 08:00
  • @AtaurRahmanMunna: I don't know. With Hibernate I didn't experience that. Maybe your implementation doesn't support proxies and has to load the entities either way? – Daniel Oct 06 '17 at 12:13
9

The book Beginning Java EE 6 Platform with GlassFish 3, mention the differences in page 135: "Finding By ID"

find() if the entity is found, it is returned; if it is not found, a null value is returned.

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

getReference() is intended for situations where a managed entity instance is needed, but no data, other than potentially the entity's primary key, being accessed.

try {
    MyEntity obj = em.getReference(MyEntity.class, id);
    // Process the object
} catch (EntityNotFoundException e) {
    // Entity Not Found
}
Jaider
  • 14,268
  • 5
  • 75
  • 82
  • ok but question : why use the getReference method, to obtain a proxy object that has the id loaded, when you already have the id, since it is needed in the getReference parameters? – Teshte Nov 05 '22 at 15:54
9

getReference() does not retrieve the full object but only a proxy and therefore can be more efficient if you do not access the members of the object.

For instance when creating a new object to insert into your database, it might have to refer to another object which already has been stored in the database.

For JPA to store the new object correctly only the primary key of the referred object is needed. By using getReference() you get a proxy which contains the primary key and you save the cost of loading the complete object.

Eelke
  • 20,897
  • 4
  • 50
  • 76