Issue Details (XML | Word | Printable)

Type: Improvement Improvement
Status: Open Open
Priority: Major Major
Assignee: tware
Reporter: pljosh
Votes: 1
Watchers: 1

If you were logged in you would be able to see more operations.

em.getReference acts like em.find which causes performance issues

Created: 25/Jun/07 05:09 PM   Updated: 06/Mar/12 10:05 PM
Component/s: entity-persistence
Affects Version/s: 9.1pe
Fix Version/s: not determined

Time Tracking:
Not Specified


Operating System: All
Platform: All

Issuezilla Id: 3,251
Participants: pkrogh, pljosh, Tom Mueller and tware

 Description  « Hide

I found that em.getReference acts the same way as em.find, I mean it does fetch
entity from database. That causes great performance issues, because everywhere I
need only a reference, TopLink is fetching entire entity which I do not really

That issue was discussed on "users" mailing list:

Following Tom Ware's suggestion, I am entering this issue as ENHANCEMENT, but
for me, it should be a DEFECT. Yes, I know "JPA spec." says:

"Get an instance, whose state may be lazily fetched."

but I believe, the JPA intention was that it may be lazily fetched only because
that entity could have been in cache already, so there would be no reason not to
provide initialized entity.
As Sahoo from SUN said /in the thread mentioned above/

"[...] I agree with you that implementing getReference() this way defeats the
purpose of having that API. I don't know the rational behind the current

pljosh added a comment - 03/Jul/07 03:13 PM

Can anyone, please, try to estimate when that issue could be fixed?
In my team, we are trying to resolve performance problems, in many cases the
source of all evil is the fact, that em.getReference is fetching entire object,
with all its dependencies, look at this example:

private void acquireLoans(BankStatement bankStatement) {
for (BankStatementEntry entry : bankStatement.getEntries()) {
String description = entry.getDescription();
Matcher matcher = LOAN_CODE_PATTERN.matcher(description);
String loanCode = matcher.find() ? : null;
if (loanCode != null) { List loanIds = em.createQuery( "SELECT FROM Loan l WHERE l.proposal.loanCode=?1") .setParameter(1, loanCode).getResultList(); if (!loanIds.isEmpty()) entry.setLoan(em.getReference(Loan.class, loanIds.get(0))); }

Instead of having one simple query per entry, em.getReference is fetching ENTIRE
Loan, Proposal and dozen of other entities, which multiplied by entires count
gives hundreds of SQL queries produced by TopLink.

Everyday I am considering changing the "issue type" into "DEFECT" as this is
really against Persistence API.

pkrogh added a comment - 05/Jul/07 07:27 AM

This section of the specification was intentionally written in this way so that
providers could implement getReference() by doing a find() or by lazily
fetching it. This is an enhancement, that does not fit into the schedule for
this release, but will be looked at for future releases.

Your example usecase is one that showcases the usefulness of lazy loading
getReference() the best, but I would argue that if performance is a concern,
there are things that you could do with this case, that would give you a much
bigger bang for your buck.

  • Using Lazy loading of relationships. By making your relationships load
    lazily, you will cut down on the SQL that gets generated by your getReference()
    call, and also improve performance in the other parts of your app.
  • Caching. By querying for PKs directly you are avoiding cache hits that
    could make getReference() and find() calls much faster.

Tom Mueller added a comment - 06/Mar/12 10:05 PM

Bulk change to set fix version to "not determined" where the issue is open but the value is for a released version.