This week's book giveaway is in the Cloud forum.
We're giving away four copies of The Business Blockchain and have William Mougayar on-line!
See this thread for details.
Win a copy of The Business Blockchain this week in the Cloud forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

EntityManager.find() vs EntityManager.getReference()

 
Sib Pete
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have come across a situation (which I think is weird but is possibly quite normal) where I use the EntityManager.getReference(LObj.getClass(), LObj.getId()) to get a database entity and then pass the returned object to be persisted in another table.

So basically the flow was like this:



I was getting the following exception "java.lang.IllegalArgumentException: Unknown entity: com.my.persistence.L$$EnhancerByCGLIB$$3e7987d0"

After looking into it for a while, I finally figured out that it was because I was using the EntityManager.getReference() method that I was getting the above exception as the method was returning a proxy.

This makes me wonder, when is it advisable to use the EntityManager.getReference() method instead of the EntityManager.find() method?

EntityManager.getReference() throws an EntityNotFoundException if it cant find the entity being searched for which is very convenient in itself. EntityManager.find() method merely returns null if it cant find the entity.

With regards to transaction boundaries, sounds to me like you would need to use the find() method before passing the newly found entity to a new transaction. If you use the getReference() method then you would probably end up in a situation similar to mine with the above exception.

ps.
I am using Hibernate as the JPA provider.
 
C Shinde
Ranch Hand
Posts: 60
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
if you look at the code:

Case 1:

Load an entity instance by its identifier value with the entity manager's find() method:



--------------------------------------------------------

Case 2:

In some cases, you don't really want to load the object state, but just having a reference to it (ie a proxy). You can get this reference using the getReference() method. This is especially useful to link a child to its parent wo having to load the parent.



So in the second case the user is trying to persist a object relation so he is only trying to associate these 2 object reference and Hibernate takes care of the rest, so I feel in this case the use of getReference() methods makes sense. But will not work if you want to retrieve the object with its relationship as getReference returns only a proxy.

I am not sure how we can use EntityManager to do eager fetching of the related objects, but thats what you are trying to do.
I think you will need to anotate the entity with something like this... , it should return the actual object with the find method.

Again Merge() works with detached objects so you to have the real object and not its proxy.
 
Sib Pete
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I do have the FetchType.Eager setting on the object.

I think the problem is that when I am calling the getReference() method, I am using the input parameter entity object's getClass() method which is actually a proxy class as returned by the earlier getReference() invocation. If use the static LClass.class instead, then it works fine.

So: LObj = EntityManager.getReference(LObj.getClass(), LObj.getId());

now becomes : LObj = EntityManager.getReference(L.class, LObj.getId());



 
C Shinde
Ranch Hand
Posts: 60
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You may like to read on this...

The ServerSide dot com
 
Sib Pete
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Things are starting to make more sense. So in my case, I definitely need to use the EntityManager.getReference() method. But the issue still remains that it returns an instance of a proxy class, i.e., when I do a getClass() method call on the object returned by the getReference() method, the object's class is of type, $$EnhancerByCGLIB$$.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic