雷蒙德SUN 2011-03-23 17:54
浏览 207
已采纳

对《深入浅出hibernate》一书中one-to-one主键关联映射疑惑

这两天在研究hibernate,发现<<深入浅出hibernate>>一书挺好,清晰易懂,只是在看到one to one 主键关联映射的地方,有些疑惑。

 

关系模型是这样的,很简单,如下:

 

T_Person

id  number(11) <pk,fk>

name varchar2(50)

age number(3)

.....

 

 

T_PASSPORT

id number(11) <pk>,

serial varchar2(20),

expiry number(11)

 

如上,T_Person的id即是主键又是外键,引用T_PASSPORT的主键字段id.并且它们是一对一的关系。

 

对应的实体类如下:

 

 

TPerson implents Serializable
+TPerson

id:Integer

age:Integer

name:String

passport:TPassport

 

 

 

TPassport implents Serializable
+Tpassport

id:Integer

serial:String

expiry:Integer

person:Tperson

 

实体关系如上,它们建立了双向一对一关系,具体映射文件如下:

 

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
     PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping>
    <class name="com.alcatel.cn.hibernate.ORMapping.onetoone.pojo.TPerson" table="T_PERSON">
        <id name="id" column="id" type="java.lang.Integer">
        <generator class="sequence">
                <param name="sequence">person_seq</param>
            </generator>
        </id>
        <property name="name" type="string" column="name"></property>
        <property name="age" type="java.lang.Integer" column="age"></property>
        <one-to-one name="passport"  class="com.alcatel.cn.hibernate.ORMapping.onetoone.pojo.TPassport"
                    cascade="all"
                    outer-join="true"/>
    </class>
</hibernate-mapping>     

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
     PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping>
    <class name="com.alcatel.cn.hibernate.ORMapping.onetoone.pojo.TPassport" table="T_PASSPORT">
        <id name="id" column="id" type="java.lang.Integer">
            
            <generator class="foreign">
                <param name="property">person</param>
            </generator>
            
        </id>
        <one-to-one name="person"
                    class="com.alcatel.cn.hibernate.ORMapping.onetoone.pojo.TPerson"
                    constrained="true"
                    ></one-to-one>
        <property name="serial" type="string" column="SERIAL"></property>
        <property name="expiry" type="java.lang.Integer" column="EXPIRY"></property>
    </class>
</hibernate-mapping>

 

    测试代码如下:

 

 

package com.alcatel.cn.hibernate.ORMapping.onetoone.test;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.alcatel.cn.hibernate.ORMapping.onetoone.pojo.TPassport;
import com.alcatel.cn.hibernate.ORMapping.onetoone.pojo.TPerson;
import com.alcatel.cn.hibernate.common.HibernateUtil;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Session s=HibernateUtil.currentSession();
        
        TPerson p=new TPerson();
        p.setAge(20);
        p.setName("Sunrui");
        
        TPassport passport=new TPassport();
        passport.setSerial("PCN759386");
        passport.setExpiry(new Integer(2));
        
        //相互设置关联
        passport.setPerson(p);
        p.setPassport(passport);
        
        
        try{
            Transaction tx=s.beginTransaction();
            
            s.save(p);//注意:这里只对Person进行保存
            tx.commit();
            
            TPassport pp=(TPassport)s.load(TPassport.class, new Integer(5));
            System.out.println("Passport Serial ==>"+pp.getSerial());
            System.out.println("Person name==>"+pp.getPerson().getName());
        }catch(Exception e){
            e.printStackTrace();
        }
    }

}

运行,出现如下异常:

 

Hibernate: select person_seq.nextval from dual
Hibernate: insert into T_PERSON (name, age, id) values (?, ?, ?)
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
    at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:92)
    at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
    at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:218)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2159)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2595)
    at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:51)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
    at com.alcatel.cn.hibernate.ORMapping.onetoone.test.Test.main(Test.java:36)
Caused by: java.sql.BatchUpdateException: ORA-02291: integrity constraint (HIBERNATE.FK_PASSPORT) violated - parent key not found

 

 

仔细把自己的代码与书中的实例对照了下,发现没有任何差错,但确确实实发生异常了。仔细分析了下,这个异常是违反了约束性,第一想到的是违反了外键 约束,看看日志(阴影部分),它确实是先往T_Person表里插入记录,当然找不到对应的T_Passport的id,违反了外键约束。

 

我尝试了把Person.hbm.xml与Passport.hbm.xml中配置方式互换,即让Passport.hbm.xml维护主键生成,然后Person.hbm.xml配置外键生成方式。运行完好。

 

这里,我从不怀疑<<深入浅出Hibernate>>作者的水平,他们确实都是比较牛的人物,也是我的偶像,像夏昕写的spring,hibernate等都是非常难得的好书。

 

所以,是不是我用的是hibernate3.0,而书本中用的是hibernate2.0等原因造成的?很迷茫。

 

 

 


问题补充
szcs10138456 写道
主键没有赋值

 

难道真的是书中的例子写错了,或者是不是我的级联关系没有设置好。。。。有点乱。谢谢你的回答。

  • 写回答

4条回答 默认 最新

  • liaohexiang 2011-03-23 17:54
    关注

    person 表的外键是 password表的主键,那么password表的主键存在才行,你的表定义也是书中给出的吗?如果是的话那就是书中有误,你的后一种交换定义的方式才是正确的

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥20 delta降尺度方法,未来数据怎么降尺度
  • ¥15 c# 使用NPOI快速将datatable数据导入excel中指定sheet,要求快速高效
  • ¥15 再不同版本的系统上,TCP传输速度不一致
  • ¥15 高德地图点聚合中Marker的位置无法实时更新
  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程