Hibernate 映射多对多关联关系
来源:互联网 发布:网络用语bgm是什么意思 编辑:程序博客网 时间:2024/05/22 14:41
Category(商品类别)和Item(商品)是多对多的关系,在关系数据模型中,无法直接表达CATEGORIES表和ITEMS表之间的多对多,需要创建一个连接表CATEGORY_ITEM,它同时参照CATEGORIES表和ITEMS表。
1.映射单向多对多关联关系
仅建立Category类到Item类的单向多对多关联,在Category类中定义items属性,而在Item类中不定义categories属性。
数据库表:
create table CATEGORIES( ID bigint not null, NAME varchar(15), primary key (ID));create table ITEMS( ID bigint not null, NAME varchar(15), BASE_PRICE double precision, primary key(ID));create table CATEGORY_ITEM( CATEGORY_ID bigint not null, ITEM_ID bigint not null, primary key(CATEGORY_ID,ITEM_ID), foreign key (CATEGORY_ID) references CATEGORIES(ID), foreign key (ITEM_ID) references ITEMS(ID));
Category.java:
public class Category implements Serializable { private Long id; private String name; private Set items=new HashSet(); constructor()...; getter()...; setter()...;}Category.hbm.xml:
<hibernate-mapping > <class name="mypack.Category" table="CATEGORIES" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" column="NAME" type="string" /> <set name="items" table="CATEGORY_ITEM" lazy="true" cascade="save-update"> <key column="CATEGORY_ID" /> <many-to-many class="mypack.Item" column="ITEM_ID" /> </set> </class></hibernate-mapping>
<set>元素的<key>子元素指定CATEGORY_ITEM表中参照CATEGORIES表的外键为CATEGORY_ID,<many-to-many>子元素的class属性指定items集合中存放的是Item对象,column属性指定CATEGORY_ITEM表中参照ITEMS表的外键是ITEM_ID。
也可以使用<idbag>、<list>和<map>元素来映射Category类的items集合。
Item.java:
public class Item implements Serializable { private Long id; private String name; private double basePrice; constructor()...; getter()...; setter()...;}Item.hbm.xml:
<hibernate-mapping > <class name="mypack.Item" table="ITEMS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" column="NAME" type="string" /> <property name="basePrice" column="BASE_PRICE" type="double" /> </class></hibernate-mapping>
2.映射双向多对多关联关系
建立Category类到Item类的双向多对多关联,在Category类中定义items属性,而在Item类中也要定义categories属性。
在双向多对多关联中,必须把其中一端的inverse属性设为true。inverse属性为false的一端可以使用<set>、<idbag>、<list>和<map>元素,而在inverse属性为true的一端只能使用<set>和<bag>元素。
<idbag>和<bag>元素的相同点在于都允许在集合中存放重复元素,并且都不支持按索引位置排序,区别在于<idbag>元素要求在连接表中必须定义代理主键,而<bag>元素没有此要求。
2.1.关联两端均使用<set>元素
数据库表:
create table CATEGORIES( ID bigint not null, NAME varchar(15), primary key (ID));create table ITEMS( ID bigint not null, NAME varchar(15), BASE_PRICE double precision, primary key(ID));create table CATEGORY_ITEM( CATEGORY_ID bigint not null, ITEM_ID bigint not null, primary key(CATEGORY_ID,ITEM_ID), foreign key (CATEGORY_ID) references CATEGORIES(ID), foreign key (ITEM_ID) references ITEMS(ID));
Category.java:
public class Category implements Serializable { private Long id; private String name; private Set items=new HashSet(); constructor()...; getter()...; setter()...;}Category.hbm.xml:
<hibernate-mapping > <class name="mypack.Category" table="CATEGORIES" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" column="NAME" type="string" /> <set name="items" table="CATEGORY_ITEM" lazy="true" cascade="save-update"> <key column="CATEGORY_ID" /> <many-to-many class="mypack.Item" column="ITEM_ID" /> </set> </class></hibernate-mapping>
Item.java:
public class Item implements Serializable { private Long id; private String name; private double basePrice; private Set categories=new HashSet(); constructor()...; getter()...; setter()...;}Item.hbm.xml:
<hibernate-mapping > <class name="mypack.Item" table="ITEMS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" column="NAME" type="string" /> <property name="basePrice" column="BASE_PRICE" type="double" /> <set name="categories" table="CATEGORY_ITEM" lazy="true" inverse="true" cascade="save-update"> <key column="ITEM_ID" /> <many-to-many class="mypack.Category" column="CATEGORY_ID" /> </set> </class></hibernate-mapping>
2.2.在inverse端使用<bag>元素
假如在Category类中已经定义了List类型的items集合,并在Item类中定义了List类型的categories集合,只有在non-inverse的一端可以使用<list>元素,那么在inverse的一端使用什么元素,显然不能使用<set>,因为<set>不能映射<list>类型的集合,为此,Hibernate提供了<bag>元素。
数据库表:
create table CATEGORIES( ID bigint not null, NAME varchar(15), primary key (ID));create table ITEMS( ID bigint not null, NAME varchar(15), BASE_PRICE double precision, primary key(ID));create table CATEGORY_ITEM( POSITION bigint not null, CATEGORY_ID bigint not null, ITEM_ID bigint not null, primary key(POSITION,CATEGORY_ID), foreign key (CATEGORY_ID) references CATEGORIES(ID), foreign key (ITEM_ID) references ITEMS(ID));
Category.java:
public class Category implements Serializable { private Long id; private String name; private List items=new ArrayList(); constructor()...; getter()...; setter()...;}Category.hbm.xml:
<hibernate-mapping > <class name="mypack.Category" table="CATEGORIES" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" column="NAME" type="string" /> <list name="items" table="CATEGORY_ITEM" lazy="true" cascade="save-update"> <key column="CATEGORY_ID" /> <index column="POSITION" /> <many-to-many class="mypack.Item" column="ITEM_ID" /> </list> </class></hibernate-mapping>
Item.java:
public class Item implements Serializable { private Long id; private String name; private double basePrice; private List categories=new ArrayList(); constructor()...; getter()...; setter()...;}Item.hbm.xml:
<hibernate-mapping > <class name="mypack.Item" table="ITEMS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" column="NAME" type="string" /> <property name="basePrice" column="BASE_PRICE" type="double" /> <bag name="categories" table="CATEGORY_ITEM" lazy="true" inverse="true" cascade="save-update"> <key column="ITEM_ID" /> <many-to-many class="mypack.Category" column="CATEGORY_ID" /> </bag> </class></hibernate-mapping>
2.3.使用组件类集合
Item和Order之间也是多对多的关联关系,可以通过专门的组件类LineItem来描述Order与Item的关联关系。
LineItem类作为组件类没有OID,LINEITEMS表为连接表。
数据库表:
create table ORDERS( ID bigint not null, ORDER_NUMBER varchar(15), primary key (ID));create table ITEMS( ID bigint not null, NAME varchar(15), BASE_PRICE double precision, primary key(ID));create table LINEITEMS( ORDER_ID bigint not null, ITEM_ID bigint not null, BASE_PRICE double precision not null, QUANTITY int not null, primary key(ORDER_ID,ITEM_ID,BASE_PRICE,QUANTITY), oreign key (ORDER_ID) references ORDERS(ID), foreign key (ITEM_ID) references ITEMS(ID));
Order.java:
public class Order implements Serializable { private Long id; private String orderNumber; private double price; private Set lineItems=new HashSet(); constructor()...; getter()...; setter()...;}Order.hbm.xml:
<hibernate-mapping > <class name="mypack.Order" table="ORDERS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="orderNumber" column="ORDER_NUMBER" type="string" /> <property name="price" formula= "(select sum(line.BASE_PRICE*line.QUANTITY) from LINEITEMS line where line.ORDER_ID=ID)" /> <set name="lineItems" lazy="true" table="LINEITEMS" > <key column="ORDER_ID" /> <composite-element class="mypack.LineItem" > <parent name="order" /> <many-to-one name="item" class="mypack.Item" column="ITEM_ID" not-null="true"/> <property name="quantity" column="QUANTITY" type="int" not-null="true" /> <property name="basePrice" column="BASE_PRICE" type="double" not-null="true" /> </composite-element> </set> </class></hibernate-mapping>
Order类的price属性被映射为了派生属性,因此在ORDERS表中不必定义PRICE字段。
Item.java:
public class Item implements Serializable { private Long id; private String name; private double basePrice; private Set lineItems=new HashSet(); constructor()...; getter()...; setter()...;}
Item.hbm.xml:
<hibernate-mapping > <class name="mypack.Item" table="ITEMS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" column="NAME" type="string" /> <property name="basePrice" column="BASE_PRICE" type="double" /> <set name="lineItems" lazy="true" inverse="true" table="LINEITEMS" > <key column="ITEM_ID" /> <composite-element class="mypack.LineItem" > <parent name="item" /> <many-to-one name="order" class="mypack.Order" column="ORDER_ID" not-null="true"/> <property name="quantity" column="QUANTITY" type="int" not-null="true" /> <property name="basePrice" column="BASE_PRICE" type="double" not-null="true" /> </composite-element> </set> </class></hibernate-mapping>
LineItem.java:
public class LineItem implements Serializable { private Item item; private Order order; private double basePrice; private int quantity; constructor()...; getter()...; setter()...;}
2.4.把多对多关联分解为两个一对多关联
对于Order与Item的多对多关联,也可以把它分解为两个一对多关联。LineItem为独立的实体类,有单独的OID。Order类与LineItem类,以及Item类与LineItem类都是一对多的双向关联关系。
LINEITEMS表作为连接表,LINEITEMS表有单独的ID代理主键。
数据库表:
create table ORDERS( ID bigint not null, ORDER_NUMBER varchar(15), primary key (ID));create table ITEMS( ID bigint not null, NAME varchar(15), BASE_PRICE double precision, primary key(ID));create table LINEITEMS( ID bigint not null, ORDER_ID bigint not null, ITEM_ID bigint not null, BASE_PRICE double precision, QUANTITY int, primary key(ID), foreign key (ORDER_ID) references ORDERS(ID), foreign key (ITEM_ID) references ITEMS(ID));
Order.java:
public class Order implements Serializable { private Long id; private String orderNumber; private double price; private Set lineItems=new HashSet(); constructor()...; getter()...; setter()...; public void setLineItems(Set lineItems) { this.lineItems = lineItems; calculatePrice(); } private void calculatePrice(){ double totalPrice=0; if(lineItems==null) return; Iterator it=lineItems.iterator(); while(it.hasNext()){ LineItem line=(LineItem)it.next(); totalPrice=totalPrice+line.getUnitPrice(); } setPrice(totalPrice); }}在setLineItems()方法中自动为price属性赋值,因此无需在Order.hbm.xml中映射price属性,也无须在ORDERS表中定义PRICE字段。setLineItems()方法调用calculatePrice()方法计算price属性值。
Order.hbm.xml:
<hibernate-mapping > <class name="mypack.Order" table="ORDERS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="orderNumber" column="ORDER_NUMBER" type="string" /> <set name="lineItems" lazy="true" inverse="true" cascade="save-update"> <key column="ORDER_ID" /> <one-to-many class="mypack.LineItem" /> </set> </class></hibernate-mapping>
Item.java:
public class Item implements Serializable { private Long id; private String name; private double basePrice; private Set lineItems=new HashSet(); constructor()...; getter()...; setter()...;}Item.hbm.xml:
<hibernate-mapping > <class name="mypack.Item" table="ITEMS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" column="NAME" type="string" /> <property name="basePrice" column="BASE_PRICE" type="double" /> <set name="lineItems" lazy="true" inverse="true" cascade="save-update"> <key column="ITEM_ID" /> <one-to-many class="mypack.LineItem" /> </set> </class></hibernate-mapping>
LineItem.java:
public class LineItem implements Serializable { private Long id; private Item item; private Order order; private double basePrice; private int quantity; constructor()...; getter()...; setter()...;}LineItem.hbm.xml:
<hibernate-mapping > <class name="mypack.LineItem" table="LINEITEMS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="quantity" column="QUANTITY" type="int" /> <property name="basePrice" column="BASE_PRICE" type="double" /> <many-to-one name="order" column="ORDER_ID" class="mypack.Order" not-null="true" /> <many-to-one name="item" column="ITEM_ID" class="mypack.Item" not-null="true" /> </class></hibernate-mapping>
所有的多对多关联都可以分解为两个一对多关联,按照这种方式映射多对多关联,会使域模型和关系数据模型具有更好的可扩展性。
- Hibernate 映射多对多关联关系
- Hibernate 映射多对多关联关系
- Hibernate关联关系映射---多对多
- Hibernate映射多对多关联关系
- Hibernate 映射多对多关联关系
- Hibernate关联关系映射(多对一关联映射)
- Hibernate关联关系映射---1对多
- Hibernate -- 映射实体关联关系(多对多关联关系)
- Hibernate关联关系映射之一对多关联关系
- Hibernate关联关系映射之多对多关联关系
- Hibernate对象关系映射-- 多对多关联关系映射
- Hibernate 关联关系映射(多对多关联)
- 【Hibernate】--关联关系映射:多对多映射
- Hibernate关联关系映射-----单向多对一映射配置
- Hibernate-映射关系- 多对多关联关系
- Hibernate关联关系映射 一对一 一对多 多对一
- Hibernate关系映射(10)_多对多单向关联
- Hibernate关系映射(11)_多对多双向关联
- 程序中上下文Context
- maven学习(下)利用Profile构建不同环境的部署包
- Spring之——quartz集群的问题及解决方案(基于Spring4.0+quartz2.2.1的集群架构)
- hdu 3572 Task Schedule(邻接表dinic)
- poj 1948(搜索+剪枝)
- Hibernate 映射多对多关联关系
- Can't load IA 32-bit .dll on a AMD 64-bit platform
- jQuery.inArray判断指定值在数组是否存在
- 字符串加密解密
- 华为机型 cordova-plugin-camera从图库获取报错
- js如何查找数组中是否存在某个值
- Matlab灰色预测和统计分析
- openFileOutput()
- JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2解决