二级缓存是否在Hibernate中是特定于会话的

时间:2014-02-19 10:49:01

标签: java hibernate ehcache

我正在学习hibernate中的二级缓存,

这是我的实体

package com.hibernate.pojo;

import java.io.Serializable;
import javax.persistence.Entity;
 import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;


@Entity
@Table(name = "customer")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@NamedQuery(query = "select c.customerName from Customer c",name = "findCustomerNames")
public class Customer implements Serializable{   

public Customer(){}
public Customer(Integer customerId){
    this.customerId = customerId;
}

public Customer(Integer customerId,String customerName){
    this.customerId = customerId;
    this.customerName = customerName;
}

@Id
private Integer customerId;
private String customerName;

/**
 * @return the customerId
 */
public Integer getCustomerId() {
    return customerId;
}

/**
 * @param customerId the customerId to set
 */
public void setCustomerId(Integer customerId) {
    this.customerId = customerId;
}

/**
 * @return the customerName
 */
public String getCustomerName() {
    return customerName;
}

/**
 * @param customerName the customerName to set
 */
public void setCustomerName(String customerName) {
    this.customerName = customerName;
}

@Override
public String toString(){
    StringBuffer strb = new StringBuffer();
    strb.append("\n\n CUSTOMER-ID : ")
            .append(this.customerId)
            .append("\n CUSTOMER-NAME : ")
            .append(this.customerName);
    return strb.toString();
}

@Override
public int hashCode(){
    return this.customerId * 29;
}

@Override
public boolean equals(Object object){
    boolean flag = false;

    if(object instanceof Customer){            
        Customer c = (Customer) object;
        flag =  (this.customerId == c.getCustomerId()) ? true : false;
    }
    return flag;
}   
}

这是我的hibernate配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

<session-factory>

    <property name="hibernate.connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
    <property name="hibernate.connection.url">jdbc:derby://localhost:1527/sun-appserv-samples</property>
    <property name="hibernate.connection.username">app</property>
    <property name="hibernate.connection.password">app</property>
    <property name="hibernate.dialect">org.hibernate.dialect.DerbyDialect</property>
    <property name="show_sql">true</property>
    <property name="format_sql">true</property>                                                
            <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>                                
            <property name="hibernate.cache.use_query_cache">true</property>
            <property name="hibernate.cache.use_second_level_cache">true</property>
            <mapping class="com.hibernate.pojo.Customer" />
</session-factory>

</hibernate-configuration>

以下代码是我的问题所在

    private static void getCustomer() throws Exception{
    Session session = HibernateUtil.getSessionFactory().openSession();
    Customer obj = null;
    obj =  (Customer)session.get(Customer.class, new Integer(2));
    session.close();
    session = HibernateUtil.getSessionFactory().openSession();
    obj = (Customer)session.get(Customer.class, new Integer(2));
    session.close();
    session = HibernateUtil.getSessionFactory().openSession();
    obj = (Customer)session.get(Customer.class, new Integer(2));        
    session.close();
    System.out.println(obj);
}

从上面的代码中你可以看到,我打开会话三次并关闭它三次。 日志中打印的查询如下

Hibernate: 
select
    customer0_.customerId as customerId0_0_,
    customer0_.customerName as customer2_0_0_ 
from
    customer customer0_ 
where
    customer0_.customerId=?

在日志中查询只打印一次,

但是当我使用下面的代码时

    private static void getCustomerFromSession() throws Exception{
    Session [] session = new Session[]{
        HibernateUtil.getSessionFactory().openSession(),
        HibernateUtil.getSessionFactory().openSession(),
        HibernateUtil.getSessionFactory().openSession()
    }; 

    Customer obj1 =  (Customer) session[0].get(Customer.class, new Integer(2));
    Customer obj2 = (Customer)  session[1].get(Customer.class, new Integer(2));
    Customer obj3 = (Customer)  session[2].get(Customer.class, new Integer(2));

    session[0].close();
    session[1].close();
    session[2].close();
}

我在这里也期望查询应该打印一次,但是日志打印

Hibernate: 
select
    customer0_.customerId as customerId0_0_,
    customer0_.customerName as customer2_0_0_ 
from
    customer customer0_ 
where
    customer0_.customerId=?
Hibernate: 
select
    customer0_.customerId as customerId0_0_,
    customer0_.customerName as customer2_0_0_ 
from
    customer customer0_ 
where
    customer0_.customerId=?
Hibernate: 
select
    customer0_.customerId as customerId0_0_,
    customer0_.customerName as customer2_0_0_ 
from
    customer customer0_ 
where
    customer0_.customerId=?

但是查询打印了三次。

我的二级缓存配置是否正确?

第二级缓存是否特定于会话?

我应该对我的代码进行哪些更改,以便即使我创建了3个会话,从第一个会话中获得的第一个客户也应该在接下来的两个会话中共享。

因此,对于与二级缓存中存在的客户相同的客户,不打印2次选择查询。

1 个答案:

答案 0 :(得分:0)

在提交事务或关闭会话时执行实际查询。由于您未单独关闭会话,因此每个get方法都会执行,因为它会处理3个不同的对象。如果在每个get方法之后关闭会话,则查找第二级缓存,并为下一个get方法检索它。因此,请尝试在每个get方法之后关闭会话。