当前有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的类也是没有问题的.
感谢各位的帮助, 谢谢!

解决方案 »

  1.   

    hibernate一级缓存和二级缓存
      

  2.   

    一对一双向关联其中有一方应该是many-to-one 吧
      

  3.   

    配的不对
    基于外键  双向一对一:
    <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>改了试试
      

  4.   

    经过本人检查, 发现自已写的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语句!感谢大家的帮忙! 谢谢!
      

  5.   

    楼主上来就肯定你的ehcache配置没有问题,为什么不把ehcache配置贴出来看看呢,我觉得如果出现你说的这种情况应该是ehcache的问题
    关于ehcache,如果不设置“查询缓存”,那么hibernate只会缓存使用load()方法获得的单个持久化对象,如果想缓存使用findall()、list()、Iterator()、createCriteria()、createQuery()等方法获得的数据结果集的话,就需要设置hibernate.cache.use_query_cache true才行.而你获取Persion对象使用的不是load方法,如果没有配置查询缓存是不能够缓存的,检查下你有没有配置查询缓存!