这是个老生长谈的问题,在学习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 class="sequence" >
<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 class="TbSceneryTickets" />
</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 class="sequence" >
<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的级联操作(增删改查)。
分享到:
相关推荐
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 双向关联...
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 双向关联...
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 双向关联...
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 双向关联...
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 三重关联...
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 双向关联...
7.2.5. 一对多关联(One-to-many Associations) 7.3. 高级集合映射(Advanced collection mappings) 7.3.1. 有序集合(Sorted collections) 7.3.2. 双向关联(Bidirectional associations) 7.3.3. 三重关联...
一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 双向关联,涉及...
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 双向关联,...
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 三重关联...
一对多关联(One-to-many Associations) 7.3. 高级集合映射(Advanced collection mappings) 7.3.1. 有序集合(Sorted collections) 7.3.2. 双向关联(Bidirectional associations) 7.3.3. 三重关联...
22.2. 双向的一对多关系(Bidirectional one-to-many) 22.3. 级联生命周期(Cascading lifecycle) 22.4. 级联与未保存值(Cascades and unsaved-value) 22.5. 结论 23. 示例:Weblog 应用程序 23.1. 持久化类 ...
6.2.5. 一对多关联(One-to-many Associations) 6.3. 高级集合映射(Advanced collection mappings) 6.3.1. 有序集合(Sorted collections) 6.3.2. 双向关联(Bidirectional associations) 6.3.3. 双向关联,...