Question

I'm now using the JPA2 @Cacheable annotation on my Entities, and all is working well.

I now need to cache a ManyToOne association.

In classic Hibernate, it was necessary to annotate the association with @Cache.

@org.hibernate.annotations.Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Student> supervisionGroup;

And this works. But it seems we cannot use the JPA2 @Cacheable annotation on anything other than the entity itself.

Am I missing something, or were the JPA committee too dim to realise that associations have to be cached as well as entities? Surely it can't be the dim option??

Was it helpful?

Solution

I think after some research I'm able to answer my own question. The key is that Hibernate dehydrates objects in the 2LC and this will influence whether you need to explicitly cache the associations.

Please add more details if I've missed anything or got any detail wrong.

Here's a simplified class structure:

@Entity
@Cacheable
public class Tutor
{
   @OneToMany(mappedBy="tutor")
   private Set<Student> students;
}

@Entity
@Cacheable
public class Student
{
   @ManyToOne(fetch=FetchType.LAZY)
   @JoinColumn(name="TUTOR_FK")
   private Tutor tutor;
}

For Hibernate

The Second Level Cache (2LC) stores entities in a dehydrated form, eg:

{1=CacheEntry(Tutor)[1, Jack Daw]}
{1=CacheEntry(Student)[1, Jane Smith, 1]}    

The final 1 in the Student data is the foreign key to tutor.

So if you have a reference to Student id 1 and follow the reference to the tutor, we get a cache hit because the foreign key is in the cache. No extra select is needed.

However, if you go the other way, calling getStudents() on the Tutor, there is no foreign key in the 2LC so a select is needed. (once the select completes, hibernate has the ids and can start hitting the 2LC).

To avoid this, you will need to add the old org.hibernate.annotations.Cache annotation to the @OneToMany relationship.

For EclipseLink

I don't have an EclipseLink installation to hand so I can't test this but I understand that EclipseLink stores the 2LC data in the form of the original object graph, so the above isn't relevant. As per Chris' answer, the entity is cached with its references so further annotating isn't needed.

OTHER TIPS

JPA's cache is for the entity objects themselves. As long as the entity is cached, so are all the references. The referenced entity objects though would have their own cache options.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top