2014-02-19 20 views
0

我學習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個會話,從第一個會話'get'獲得的第一個客戶也應該由下兩個會話共享。

因此沒有打印2選擇同一客戶的查詢,因爲它存在於二級緩存中。

回答

0

實際查詢在您提交事務或會話關閉時執行。由於您沒有單獨關閉會話,每個get方法都會被執行,因爲它會處理3個不同的要加載的對象。如果在每個get方法之後關閉會話,則會查找二級緩存,並且將爲下一個get方法檢索它。因此,請嘗試在每次獲取方法後關閉會話。