读书人

Hibernate在one-to-many兑现父子关系的

发布时间: 2012-09-29 10:30:01 作者: rapoo

Hibernate在one-to-many实现父子关系的自动插入

????? 这是个老生长谈的问题,在学习Hibernate的时候,当时是认为永远都用不上,因为现在数据库设计并没有严格按照范式来进行设计,更多的时候采用逻辑外键关系,在代码中去控制这种业务逻辑。但是,这次在'景点+门票'的1-N关系模型时候产品设计了插入景点信息时候就录入N个门票类型信息。所以,个人认为在插入(CMS中数据的录入时候)使用起来这种级联增删改比较方便,因为插入不会带来巨大数据库压力(hibbernate的这种级联操作确实效率不高,从打印出来的HQL中可以明显看到,Hibernate对N的一端也是一条插入的)。

?

景点 和 门票类型的POJO和hbm代码

景点POJO

public class TbScenery {private String id;private String jdname;private List<TbSceneryTickets> tbSceneryTickets;//getter setter....}

景点hbm

<?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>    <class name="TbScenery" table="TB_SCENERY">        <id name="id" type="java.lang.String">            <column name="ID" length="32" />            <generator >      <param name="sequence">SEQ_SCENERY</param>      </generator>        </id>        <property name="jdname" type="java.lang.String">            <column name="JDNAME" length="500" />        </property><!-- 这里需要Parent一端设置inverse="true" cascade="all"--><list name="tbSceneryTickets" lazy="false" inverse="true" cascade="all"><key><column name="SCENERY_ID" /></key><index column="ID" type="java.lang.String" /><one-to-many /></list>    </class></hibernate-mapping>

?

门票POJO:

public class TbSceneryTickets implements java.io.Serializable {private String id;private String sceneryId;//外键private String typeName;//getter setter....}

门票hbm

<hibernate-mapping><class name="TbSceneryTickets" table="TB_SCENERY_TICKETS" lazy="false">        <id name="id" type="java.lang.String">            <column name="ID" length="32" />            <generator >      <param name="sequence">SEQ_SCENERY_TICKET</param>      </generator>        </id><property name="sceneryId" type="java.lang.String" column="SCENERY_ID"length="32" /><property name="typeName" type="java.lang.String" column="TYPE_NAME"length="100" /></class></hibernate-mapping>

?

测试后发现在做更新,删除操作的时候的时候没有任何问题,只是在做如下的插入操作的时候会发现插入失败(这里的方法用了事务控制):

public void test() {TbScenery scenery = new TbScenery();scenery.setJdname("东方明珠");//由于景点对象的id主键 和 门票对象的id主键都是从序列中获取到的,这里没法设置这些值。//也没有办法为门票对象赋景点外键sceneryId的值TbSceneryTickets ticket1 = new TbSceneryTickets();ticket1.setTypeName("成人票");TbSceneryTickets ticket2 = new TbSceneryTickets();ticket1.setTypeName("儿童票");List<TbSceneryTickets> tbSceneryTickets = new ArrayList<TbSceneryTickets>();tbSceneryTickets.add(ticket1);tbSceneryTickets.add(ticket2);scenery.setTbSceneryTickets(tbSceneryTickets);dao.saveOrUpdate(scenery);}
?

????? 原因是:在新建’景点‘,并且有了n个’门票类型的时候‘,不能一次性提交这个’景点‘对象,tbSceneryTickets赋值给scenery前需要先save一下scenery,因为scenery是一个new出来的对象,不是一个已经被持久化过的对象,对它进行tbSceneryTickets赋值,Hibernate并不能够检查到它的状态。其实说得浅显些,就是scenery(景点对象)自己都没有id标识,那每个TbSceneryTickets对象(门票类型对象)怎么知道外键是什么呢?

???? 对于one-to-many,一般都是如下操作:

public void test() {TbScenery scenery = new TbScenery();scenery.setJdname("东方明珠");//这个步骤结束后,scenery就有自己的主键了,通过debug可以非常清楚的看到dao.saveOrUpdate(scenery);TbSceneryTickets ticket1 = new TbSceneryTickets();ticket1.setTypeName("成人票");//当然如果不放心,可以自己手工给ticket赋外键ticket1.setSceneryId(scenery.getId());TbSceneryTickets ticket2 = new TbSceneryTickets();ticket1.setTypeName("儿童票");ticket2.setSceneryId(scenery.getId())List<TbSceneryTickets> tbSceneryTickets = new ArrayList<TbSceneryTickets>();tbSceneryTickets.add(ticket1);tbSceneryTickets.add(ticket2);scenery.setTbSceneryTickets(tbSceneryTickets);dao.saveOrUpdate(scenery);}

?

在项目中可以使用这个原理来轻松完成one-to-many的级联操作(增删改查)。

读书人网 >开源软件

热点推荐