2010-02-18 15 views
8

Digamos que tengo dos entidades, Employee y Skill. Cada empleado tiene un conjunto de habilidades. Ahora cuando cargo las habilidades perezosamente a través de las instancias Employee, la caché no se usa para habilidades en diferentes instancias de Employee.¿Cómo usar la memoria caché de segundo nivel para colecciones cargadas perezosas en Hibernate?

Consideremos el siguiente conjunto de datos.

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

Cuando cargo del empleado - 2 después de Empleado - 1, no quiero hibernar para golpear la base de datos para obtener las habilidades y en su lugar utilizar los Skill casos ya está disponible en la memoria caché. es posible? ¿Si es así, cómo?

configuración de hibernación

<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> 

las entidades con las importaciones, captadores y definidores Eliminado

@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 para cargar el segundo de los empleados y sus habilidades

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=? 

Quiero evitar específicamente la segunda consulta, ya que la primera es inevitable de todos modos.

Respuesta

4

Debe almacenar en caché la asociación Employee--<>Skills. Ejemplo tomado de Speed Up Your Hibernate Applications with Second-Level Caching a continuación:

<hibernate-mapping package="com.wakaleo.articles.caching.businessobjects"> 
    <class name="Employee" table="EMPLOYEE" dynamic-update="true"> 
     <meta attribute="implement-equals">true</meta>  

     <id name="id" type="long" unsaved-value="null" > 
      <column name="emp_id" not-null="true"/> 
      <generator class="increment"/> 
     </id> 

    <property column="emp_surname" name="surname" type="string"/> 
    <property column="emp_firstname" name="firstname" type="string"/> 

    <many-to-one name="country" 
      column="cn_id" 
       class="com.wakaleo.articles.caching.businessobjects.Country" 
      not-null="true" /> 

    <!-- Lazy-loading is deactivated to demonstrate caching behavior -->  
    <set name="languages" table="EMPLOYEE_SPEAKS_LANGUAGE" lazy="false"> 
     <cache usage="read-write"/> 
     <key column="emp_id"/> 
      <many-to-many column="lan_id" class="Language"/> 
    </set>        
    </class> 
</hibernate-mapping> 

Nota el elemento <cache> dentro de la de las lenguas.

+0

Ya he hecho esto. Evita la consulta solo para aquellos empleados que ya están cargados. No empleados que no están en caché y que también tienen las mismas habilidades que otro empleado que ya está en el caché. En mi ejemplo inicial, funcionaría si cargo Empleado - 1 nuevamente pero no cuando cargo Empleado - 2. –

+0

@Chandru ¿Puede mostrar sus asignaciones ** y ** el SQL generado? –

+0

He actualizado mi pregunta para agregar la información. –

Cuestiones relacionadas