关于Hibernate ehcache二级缓存的问题(有点难度), 请帮忙, 谢谢!

ABC123CBA321 2009-09-27 07:17:54

当前有Person与IdCard两个一对一关联关系的类, 当我设置了二级缓存之后, 出现了异常, 请看源代码:



// Person.java
package bean;
public class Person {
private Integer id;
private String name;
private IdCard idCard;
// set, get省略
}




// IdCard.java
package bean;
import java.util.Date;
public class IdCard {
private Integer id;
private Date useFulLife;
private Person person;
// set, get省略
}




<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="bean">
<class name="Person">
<cache usage="read-write" />
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<one-to-one name="idCard" property-ref="person"/>
</class>
</hibernate-mapping>





// IdCard.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="bean">
<class name="IdCard" table="id_card">
<cache usage="read-write" />
<id name="id">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="useFulLife" column="useful_life"/>
<one-to-one name="person" constrained="true"/>
</class>
</hibernate-mapping>




//One2One.java
package hibernate;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.stat.Statistics;

import bean.IdCard;
import bean.Person;

public class One2One {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
add();
testCache();
}

public static void testCache() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Session session = null;
try {
// 从HibernateUtil中获取session
session = HibernateUtil.getSession();

Person p1 = (Person) session.get(Person.class, 1);
Person p2 = (Person) session.get(Person.class, 1);

Statistics s = HibernateUtil.getSessionFactory().getStatistics();
System.out.println(s);

} finally {
if (null != session)
session.close();
}

try {
session = HibernateUtil.getSession();
Person p3 = (Person) session.get(Person.class, 1);
} finally {
if (null != session)
session.close();
}

}

public static void testQuery() {
Session session = null;
try {
session = HibernateUtil.getSession();
Person person = (Person) session.get(Person.class, 1);
// IdCard idCard = (IdCard)session.load(IdCard.class, 1);
System.out.println("person.class: " + person.getClass());

Person person1 = (Person) session.get(Person.class, 1);
System.out.println("person1.class: " + person1.getClass());
} finally {
if (null != session)
session.close();
}
}

public static void add() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();

IdCard idCard = new IdCard();
idCard.setUseFulLife(new Date());
Person person = new Person();
person.setName("pserson1 name");

person.setIdCard(idCard);
idCard.setPerson(person);

tx = session.beginTransaction();

session.save(person);
session.save(idCard);

tx.commit();
} finally {
if (null != session) {
session.close();
}
}
}
}




当运行此程序时, 出现以下异常信息:
Hibernate: insert into Person (name) values (?)
Hibernate: insert into id_card (useful_life, id) values (?, ?)
Hibernate: select person0_.id as id5_1_, person0_.name as name5_1_, idcard1_.id as id6_0_, idcard1_.useful_life as useful2_6_0_ from Person person0_ left outer join id_card idcard1_ on person0_.id=idcard1_.id where person0_.id=?
Hibernate: select idcard0_.id as id6_0_, idcard0_.useful_life as useful2_6_0_ from id_card idcard0_
Exception in thread "main" org.hibernate.exception.GenericJDBCException: could not load an entity: [bean.IdCard#1]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1874)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
at org.hibernate.loader.entity.EntityLoader.loadByUniqueKey(EntityLoader.java:85)
at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:1649)
at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:608)
at org.hibernate.type.EntityType.resolve(EntityType.java:382)
at org.hibernate.type.OneToOneType.assemble(OneToOneType.java:141)
at org.hibernate.type.TypeFactory.assemble(TypeFactory.java:420)
at org.hibernate.cache.entry.CacheEntry.assemble(CacheEntry.java:96)
at org.hibernate.cache.entry.CacheEntry.assemble(CacheEntry.java:82)
at org.hibernate.event.def.DefaultLoadEventListener.assembleCacheEntry(DefaultLoadEventListener.java:557)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromSecondLevelCache(DefaultLoadEventListener.java:512)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:357)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:195)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:815)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)
at hibernate.One2One.testCache(One2One.java:36)
at hibernate.One2One.main(One2One.java:15)
Caused by: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3288)
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3272)
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3314)
at com.mysql.jdbc.PreparedStatement.setInt(PreparedStatement.java:3258)
at org.hibernate.type.IntegerType.set(IntegerType.java:41)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:136)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:116)
at org.hibernate.loader.Loader.bindPositionalParameters(Loader.java:1707)
at org.hibernate.loader.Loader.bindParameterValues(Loader.java:1678)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1563)
at org.hibernate.loader.Loader.doQuery(Loader.java:673)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1860)
... 20 more



以上程序我运行在"没有关联关系的类"时不会出错, 曾做过User单个类的测试, 能够正确运行!
但运行在此"一对一关联关系的用例"时却报异常了, 不知道是什么原因.
首先说明, 我的ehcache的配置是正确的, HibernateUtil的类也是没有问题的.
感谢各位的帮助, 谢谢!
...全文
542 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
北漂 2010-12-30
  • 打赏
  • 举报
回复
楼主上来就肯定你的ehcache配置没有问题,为什么不把ehcache配置贴出来看看呢,我觉得如果出现你说的这种情况应该是ehcache的问题
关于ehcache,如果不设置“查询缓存”,那么hibernate只会缓存使用load()方法获得的单个持久化对象,如果想缓存使用findall()、list()、Iterator()、createCriteria()、createQuery()等方法获得的数据结果集的话,就需要设置hibernate.cache.use_query_cache true才行.而你获取Persion对象使用的不是load方法,如果没有配置查询缓存是不能够缓存的,检查下你有没有配置查询缓存!

ABC123CBA321 2009-09-29
  • 打赏
  • 举报
回复
经过本人检查, 发现自已写的XML配置确实有误, 后来改为[一对一外键关联关系]运行之后就没有抛异常了.

但还是存在以下问题:


public static void testCache() {
Session session = null;
try {
session = HibernateUtil.getSession();
Person p1 = (Person) session.get(Person.class, 1);
Person p2 = (Person) session.get(Person.class, 1);

Statistics s = HibernateUtil.getSessionFactory().getStatistics();
System.out.println(s);

} finally {
if (null != session)
session.close();
}

try {
session = HibernateUtil.getSession();
Person p3 = (Person) session.get(Person.class, 1);
} finally {
if (null != session)
session.close();
}
}


按照以上的代码来讲, 我已经配置了二级缓存ehcache, 所以只会输出一条select语句, 讲解如下:
(1). p1从数据库里拿出Person之后, 便放入一级缓存和二级缓存.
(2). p2从一级缓存取出Person
(3). p3从一级缓存里找Person, 但找不到, 因为session已经关闭. 然后p3从二级缓存里取出Person.

但是结果却产生了两条select语句, 第一句是在(1)里产生的, 这个正常, 因为get方法要从数据库里取数据.
问题是第(3)也产生了一条select语句, 按道理来讲不应该会产生的, 请问这是为什么呢?


本人曾经做过[没有任何关联关系的单个Person类]测试, 结果运行正常, 同样的代码情况下只产生一条select语句
但后来给Person加上IdCard作为one-to-one的关联关系时却产生了两条select语句!

感谢大家的帮忙! 谢谢!
superjava_2006 2009-09-28
  • 打赏
  • 举报
回复

支持楼上,感觉也是配置问题,看报的异常不是缓存问题,是取不到关联的对象。
chpublish1012 2009-09-28
  • 打赏
  • 举报
回复
配的不对
基于外键 双向一对一:
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
unique="true"
not-null="true"/>
</class>

<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<one-to-one name="person"
property-ref="address"/>
</class>

改了试试
wing_88 2009-09-28
  • 打赏
  • 举报
回复
一对一双向关联其中有一方应该是many-to-one 吧
Defonds 2009-09-28
  • 打赏
  • 举报
回复
水中影子 2009-09-28
  • 打赏
  • 举报
回复
同意楼上的,很容易搞混

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧