How to use second level cache for lazy loaded collections in Hibernate?

Posted by Chandru on Stack Overflow See other posts from Stack Overflow or by Chandru
Published on 2010-02-18T10:57:22Z Indexed on 2010/05/01 0:57 UTC
Read the original article Hit count: 400

Let's say I have two entities, Employee and Skill. Every employee has a set of skills. Now when I load the skills lazily through the Employee instances the cache is not used for skills in different instances of Employee.

Let's Consider the following data set.

Employee - 1 : Java, PHP
Employee - 2 : Java, PHP

When I load Employee - 2 after Employee - 1, I do not want hibernate to hit the database to get the skills and instead use the Skill instances already available in cache. Is this possible? If so how?

Hibernate Configuration

<session-factory>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.password">pass</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost/cache</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>

    <property name="hibernate.cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.use_query_cache">true</property>
    <property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</property>
    <property name="hibernate.hbm2ddl.auto">update</property>
    <property name="hibernate.show_sql">true</property>

    <mapping class="org.cache.models.Employee" />
    <mapping class="org.cache.models.Skill" />
</session-factory>

The Entities with imports, getters and setters Removed

@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name;

    public Employee() {
    }

    @ManyToMany
    @JoinTable(name = "employee_skills", joinColumns = @JoinColumn(name = "employee_id"), inverseJoinColumns = @JoinColumn(name = "skill_id"))
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    private List<Skill> skills;
}

@Entity
@Table(name = "skill")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Skill {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name;
}

SQL for Loading the Second Employee and his Skills

Hibernate: select employee0_.id as id0_0_, employee0_.name as name0_0_ from employee employee0_ where employee0_.id=?
Hibernate: select skills0_.employee_id as employee1_1_, skills0_.skill_id as skill2_1_, skill1_.id as id1_0_, skill1_.name as name1_0_ from employee_skills skills0_ left outer join skill skill1_ on skills0_.skill_id=skill1_.id where skills0_.employee_id=?

In that I specifically want to avoid the second query as the first one is unavoidable anyway.

© Stack Overflow or respective owner

Related posts about java

Related posts about hibernate