[英]Hibernate Session.merge() hits second level cache, but saveOrUpdate does not
[英]Is second level cache is Session specific in 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;
}
}
这是我的休眠配置文件
<?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选择查询的打印。
当您提交事务或关闭会话时,将执行实际查询。 由于您没有分别关闭会话,因此将执行每个get方法,因为将其视为要加载的3个不同对象。 如果在每个get方法之后关闭该会话,则将查找二级缓存,并将为下一个get方法进行检索。 因此,尝试在每个get方法之后关闭会话。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.