1

I use JPA with Hibernate implementation. My question is probably basic for experienced hibernate users: what is the most efficient way to write queries based on Hibernate first level cache?

For example, I have entity A and entity B:

@Entity
class A{
      private int ida;
      private int x;
      private String s;
    @OneToMany(mappedBy = "ida", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
      private Set<B> Bset;
    }

@Entity
class B{
      private int ida;
      private String s2;
    }

Suppose I have several flows that may happen in the same session:

  1. get A.x
  2. get the whole A entity
  3. check if A contains B with s2="...";

For every one of these queries I can

  • write a specific query that gets A.x / B by ida and s2 or
  • suppose that Hibernate saves cache and always get A object, or A.Bset() and then java loops to get the needed B inside Bset()

What is the most efficient way?

thank you

2 Answers 2

1

For use cases 1 and 2 I would just load the whole entity. Second level cache will work equally well. Unless your A object is really big (has a lot of properties) you won't see see any difference compared to:

SELECT a.x FROM A a WHERE a.id = :id

Even worse, using the query above will not take advantage of L2 cache.

Third use case is more interesting. It heavily depends on your requirements, but the reasonable balance would be to use a query like this:

SELECT B b
WHERE b.s2 == :s2
  AND b.a = :a

If the query returns something it means a contains b with given s2. This should be much faster than lazily loading Bset and iterating over it. Consider enabling query cache.

However if Bset is typically small and you use eager fetching, simple filtering in Java might be better. It really depends on your architecture.

Sign up to request clarification or add additional context in comments.

3 Comments

thank you, that solved some of my use cases. What is recommended if once I need a single B row, I will need the whole Bset? I think that eager fetching would bring B rows for A.Bset one by one.
No, eager fetching is actually used to prevent one-by-one fetching (infamous N+1 problem). With eager fetching Hibernate will create a JOIN query for you and fetch A with all Bs at once with one SQL.
This is configured using the @FetchMode(JOIN)
1

Just a warning that I don't think the above mapping between A and B will work. When you use mappedBy on the OneToMany side of the relationship you need to also map the reverse relationship in B.

@Entity
class B{
      @ManyToOne
      @JoinColumn(name="aid")
      private A a;
      private String s2;
    }

A OneToMany unidirectional relationship isn't really recommended.

In answer to your question, the key to using the Session cache efficiently is to use get() wherever possible. So if you can get A by its @Id you can iterate through the mapped collection of B to find the instance you're interested in.

Using get will ensure that if the instance of A you're after is in the cache it will just be returned (very fast) and if it's not in the cache it will be added to the cache and then returned to you. Then next time you ask for it by @Id it will be returned from the cache.

Whenever you use HQL and force Hibernate to perform a query you will bypass the Session cache and go straight to the database. If you find yourself needing to perform queries which miss the cache it might be worth looking into Query caching.

2 Comments

Thanks for the answer. You wrote: "Then next time you ask for it by @ Id it will be returned from the cache.". I never query by ID column, I query by @ UniqueConstraint. Will it still be returned from the cache? (equals and hashcode are based on UniqueConstraint too)
I don't think it will. As I understand it the session cache is essentially a big map of Ids to Objects. Therefore to get entities from it you have to be using the Id.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.