Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

JPA: @OrderBy bypassed by cache?

 
Per Lindberg
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It appears that the @OrderBy annotation on a @OneToMany LinkedList member of an @Entity does not work when another item is added last to the list by a @Stateless session bean. The next access (by later HTTP request to a @Stateless session bean) calling myEntityManager.find will see an unsorted list. Restarting the app server solves the problem. My guess is that the JPA/ORM engine keeps a cache and don't give a hoot about @OrderBy. Example:



The first request does a carModelLocal.create(carMakerId, name, year);

The second request does a CarMaker carMaker = carMakerLocal.find(carMakerId)); which returns em.find(persistentClass, id);

The resulting carMaker has the new CarModel last in the LinkedList, ignoring @OrderBy. Aarrgh!

As I said, the probable culprit is some cache in the JPA/ORM engine. I use Glassfish v2.

Is this a bug or a feature?

What would be a canoncial workaround? Adding "manual" sorting in getCarModels()? Or is there a better way?

 
James Sutherland
Ranch Hand
Posts: 553
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you want to have the List ordered you need to maintain the order when you add to it. In your addCarModel() method in your object you can use Collections.sort() to fix the order after adding to it.

You could also use a TreeSet to automatically maintain the order, but this would not work with a LAZY mapping.

In JPA 2.0 there is also support for an OrderColumn which maintains the order in the database as define in the object model.

See also,
http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Ordering

To disable caching in TopLink Essentials (default provider in Glassfish 2), you can use "toplink.cache.shared.default"="false" in your persistence.xml.

You can also call refresh() on the object, to refresh it from the database.
 
Per Lindberg
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks James! Crystal clear explanation.

It appears that the best solution in this case is to add Collartions.sort() to all business methods that inserts (and renames!) List members. Re-sorting on each access seems ineffective. Ditto disabling the cache or calling refresh().
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic