- 浏览: 108551 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
ldwtill:
overwrite呢?
overload,overwrite和override比较 -
dafeiwang:
...
过滤器和拦截器的区别
Hibernate关联关系 收藏
一, 一对多的单向关联关系
首先先建立Customer和Order类,代码如下:
Customer类:
package mypack; import java.io.Serializable; import org.apache.commons.lang.builder.ToStringBuilder;
public class Customer implements Serializable {
private Long id;
private String name;
public Customer(String name) { this.name = name; }
public Customer() { }
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public String toString() { return new ToStringBuilder(this) .append("id", getId()) .toString(); }
}
Order类:
package mypack; import java.io.Serializable; import org.apache.commons.lang.builder.ToStringBuilder;
public class Order implements Serializable {
private Long id;
private String orderNumber;
private mypack.Customer customer;
public Order(String orderNumber, mypack.Customer customer) { this.orderNumber = orderNumber; this.customer = customer; }
public Order() { }
public Order(mypack.Customer customer) { this.customer = customer; }
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getOrderNumber() { return this.orderNumber; }
public void setOrderNumber(String orderNumber) { this.orderNumber = orderNumber; }
public mypack.Customer getCustomer() { return this.customer; }
public void setCustomer(mypack.Customer customer) { this.customer = customer; }
public String toString() { return new ToStringBuilder(this) .append("id", getId()) .toString(); }
}
Customer和Order类的配置文件分别是Customer.hbm.xml和Order.hbm.xml
Customer.hbm.xml如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping >
<class name="mypack.Customer" table="CUSTOMERS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id>
<property name="name" type="string" > <column name="NAME" length="15" /> </property>
</class>
</hibernate-mapping>
Order.hbm.xml如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping >
<class name="mypack.Order" table="ORDERS">
<id name="id" type="long" column="ID"> <generator class="increment"/> </id>
<property name="orderNumber" type="string" > <column name="ORDER_NUMBER" length="15" /> </property>
<many-to-one name="customer" column="CUSTOMER_ID" class="mypack.Customer" not-null="true" />
</class>
</hibernate-mapping>
在Order.hbm.xml中<many-to-one>元素建立了Customer和ORDERS表的外键CUSTOMER_ID之间 的映射。 它包括如下属性。
● name:设定待映射的持久化类的属性名,此处为Order类的customer属性。 ● column:设定和持久化类的属性对应的表的外键,此处为ORDERS表的外键CUSTOMER_ID。 ● class:设定持久化类的属性的类型,此处设定customer属性为Customer类。 ● not-null:如果为ture,表示customer属性不能为null,默认为false。
接下来我们持久化一个Customer对象以及和他关联的Order对象: (以下代码并非是完整代码,只是简单把逻辑列出)
Configuration config = new Configuration(); config.addClass(Customer.class) . addClass(Order.class); sessionFactory = config.buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction tx = null; tx = session.beginTransaction(); Customer customer=new Customer("Jack"); session.save(customer); Order order1=new Order("Jack_Order001",customer); Order order2=new Order("Jack_Order002",customer); session.save(order1); session.save(order2); tx.commit();
当我们要持久化一个Customer对象以及和他关联的Order对象的时候一定要先建立Customer对象并持久化它,否则当创建Order持久对象的时候会抛出异常,如果把session.save(customer) 注销将会在session.save(order1)抛出PropertyValueException异常。分析产生异常原因:在调用session.save(order1)方法之前,order1和customer对象都是临时对象,临时对象就是刚刚用new创建出来,但是还没有持久会的对象,而Hibernate不会自动持久化order1关联的customer对象,在数据库中意味着仅仅向ORDERS表中插入了一条记录,并且该记录的CUSTOMER_ID字段为null,违反了数据库完整性约束,因为不允许ORDERS表的CUSTOMER_ID字段为null。
从上面的例子可以看出当Hibernate持久化一个临时对象时,在默认情况下,它不会自动持久化所关联的其他临时对象,所以会抛出PropertyValueException异常。如果希望当Hibernate持久化Order对象时自动持久化所关联的Customer对象,可以把<many-to-one>的cascade属性设为“save-update”,cascade属性默认为“none”:
<many-to-one name="customer" column="CUSTOMER_ID" class="mypack.Customer" cascade=“save-update” not-null="true" />
这样就能够在Hibernate持久化Order对象时自动持久化所关联的Customer对象了。
二, 一对多的双向关联关系
我们依然使用前面的Customer和Order的例子,由于是双向关联,Order类代码如上面一样,由于Customer类中有Order的关联对象,因此Customer类改为如下:
package mypack;
import java.io.Serializable; import java.util.Set; import org.apache.commons.lang.builder.ToStringBuilder;
public class Customer implements Serializable {
private Long id;
private String name;
private Set orders;
public Customer(String name, Set orders) { this.name = name; this.orders = orders; }
public Customer() { }
public Customer(Set orders) { this.orders = orders; }
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public Set getOrders() { return this.orders; }
public void setOrders(Set orders) { this.orders = orders; }
public String toString() { return new ToStringBuilder(this) .append("id", getId()) .toString(); }
}
如何在映射文件中映射集合类型的order属性呢?由于在CUSTOMERS表中没有直接与order属性对应的字段,因此不能用<property>元素来映射order属性,而是要使用<set>元素:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping >
<class name="mypack.Customer" table="CUSTOMERS" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id>
<property name="name" type="string" > <column name="NAME" length="15" /> </property>
<set name="orders" cascade="save-update"
>
<key column="CUSTOMER_ID" /> <one-to-many class="mypack.Order" /> </set> </class> </hibernate-mapping>
<set>元素还包含两个子元素:<key>和<one-to-many>,<one-to-many>元素设定所关联的持久化类,此处为Order类,<key>元素设定与所关联的持久化对应的表的外键,此处为ORDERS表的CUSTOMERS_ID字段。 它包括如下属性: ● <set>元素表明Customer类的orders属性为java.util.Set集合类型。 ● <one-to-many>表明orders集合中存放的是一组Order对象。 ● <key>属性表明ORDERS表通过外键CUSTOMERS_ID参照CUSTOMERS表。 ● cascade 属性取值为"save-update",表明当保存或更新Customer对象时,会级联保存或更新orders集合中的所有Order对象。
接下来我们持久化一个Customer对象以及和他关联的Order对象:
Session session = sessionFactory.openSession(); Transaction tx = null; tx = session.beginTransaction(); Customer customer=new Customer("Tom",new HashSet()); Order order=new Order(); order.setOrderNumber("Tom_Order001"); order.setCustomer(customer); customer.getOrders().add(order); session.save(customer); tx.commit();
当<set>元素的cascade属性为"save-update"时,Hibernate在持久化Customer对象时,会自动持久化关联的Order对象。
如果是加载持久化对象,然后再建立关联关系,那又该怎么做呢?如下所示:
Session session = sessionFactory.openSession(); Transaction tx = null; tx = session.beginTransaction(); Customer customer=(Customer)session.load(Customer.class,new Long(2)); Order order=(Order)session.load(Order.class,new Long(2)); order.setCustomer(customer); customer.getOrders().add(order); tx.commit();
Hibernate会自动清理缓存中的所有持久化对象,按照持久化对象状态改变来同步更新数据库,Hibernate在清理以上Customer对象和Order对象时执行了以下两条SQL语句: update ORDERS set ORDER_NUMBER='Jack_Order001',CUSTOMER_ID=2 where ID=2; update ORDERS set CUSTOMER_ID=2 where ID=2; 尽管只是修改了ORDERS表的一条记录,但是以上SQL语句表明Hibernate执行了两次update操作这是因为HIbernate根据内存中持久化对象的状态变化来决定需要执行的SQL语句,order.setCustomer(customer)执行的相应SQL语句为: update ORDERS set ORDER_NUMBER='Jack_Order001',CUSTOMER_ID=2 where ID=2; customer.getOrders().add(order)执行的相应SQL语句为: update ORDERS set CUSTOMER_ID=2 where ID=2; 重复执行对于的SQL语句会影响应用程序的性能,那么解决的办法是把<set>元素的inverse属性设置为true,默认为false:
<set name="orders" cascade="save-update" inverse="ture" >
<key column="CUSTOMER_ID" /> <one-to-many class="mypack.Order" /> </set> 因此在映射一对多双向关联关系时,应该在"one"方把inverse属性设为“ture”,这样可以提高性能。 |
发表评论
-
hibernate五大核心接口及其应用
2011-05-02 20:28 895所有的Hibernate应用中都会访问Hibernate的5个 ... -
hibernate fetch 和lazy
2011-05-02 19:42 1074经过测试发现Hibernate annotation ... -
hibernate优化
2011-05-02 09:56 744口诀 1、使用双向一对多关联, ... -
Hibernate详解(一)------->>入门
2011-05-02 09:35 777Hibernate是一个开放源代码的对 ... -
hibernate详解(二)---->>继承关系映射(一)
2011-05-02 09:34 811继承是面对对象编程中一个很 ... -
hibernate详解(二)----->>继承关系映射(二、三)
2011-05-02 09:33 788这篇文章紧接着hibernate详解(二)- ... -
hibernate详解(三)----->>组件映射(一)
2011-05-02 09:33 791Hibernate建议在进行领域模型建模时要细 ... -
hibernate详解(三)----->>组件映射(二)之复合主键
2011-05-02 09:31 9433、组件类作为持久化类的对象标识符属性 ... -
Hibernate详解(四)---->>关联关系映射(二)
2011-05-02 09:29 9593、单向一对一 每个中国公民都有一张身份证 ... -
Hibernate详解(四)---->>关联关系映射(一)
2011-05-02 09:27 837关联关系是在领域模型建模中经常使用到的一 ... -
hibernate的二级缓存
2011-05-02 08:58 605Hibernate二级缓存也称为进程级的缓存或Sessio ... -
全面讲解Hibernate二级缓存
2011-05-02 08:56 667在向大家详细介绍Hibernate二级缓存之前,首先让大家了解 ... -
hibernate工作原理及为什么要使用
2011-05-02 08:51 898Hibernate工作原理及其作用 Java学习笔记 201 ... -
hibernate连接池
2011-05-02 08:49 795我分别用以下链接方式测试了一下:tomcat自带的连接池< ... -
Hibernate Criteria Query
2011-05-02 08:34 668Hibernate-Criteria Query 收藏 Cri ... -
hibernate----Inverse 和 cascade区别
2011-05-02 08:15 821Inverse 和 cascade的区别 ... -
Spring中配合hibernate使用的简单例子
2011-05-01 20:42 671最近在看SPRING和hibernate,学习了sprin ... -
hibernate 之inverse重点复习
2011-05-01 20:00 678inverse的原因,在于单向的一对多的低效而造成的.举个 ... -
hibernate中只选取某些列的写法
2011-05-01 18:44 784在普通的sql中,为了选取某些列,其实是很简单的,就sele ... -
HQL返回值
2011-05-01 18:35 1201Hibernate查询单个字段,Hibernate把每个id做 ...
相关推荐
hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的...
该资源包含了一些常用的hibernate关联映射实例。包括一对多,多对多,继承映射,等,是学习hibernate的必备品
Hibernate关联关系练习【全】
hibernate关联关系
映射一对多关联关系 以Customer和Order为例: 一对多: 每个Customer可以有一个或者多个Order,因此Customer中应该有一个集合类型的属性,来引用所有关联的Order对象。 多对一。全实例讲解
Hibernate关联关系映射 单向关联 │ ├─ 一对一外键单向关联 │ ├─ 一对一主键单向关联 │ ├─ 一对一连接表单向关联 │ ├─ 一对多外键单向关联 │ ├─ 一对多连接表单向关联 │ ├─ 多对一外键单向关联 │ ...
hibernate关联查询 实例源码 java web 如果不明白hibernate关联查询不明白的可以看看,保证马上学会,注释,数据库都有,很简单易学的源码,谢谢下载!
Hibernate 一对一外键单向关联 Hibernate 一对一主键单向关联 Hibernate 一对一连接表单向关联 Hibernate 一对多外键单向关联 Hibernate 一对多连接表单向关联 Hibernate 多对一外键单向关联 Hibernate 多对一连接...
Hibernate 关联关系映射分类
文件中包含关于hibernate 各个属性的解释
Hibernate关联关系.docHibernate关联关系.doc
Hibernate关联关系总结 一对多 多对一 多对多
大致总结了一下Hibernate关联关系。提供相关的一些例子进行测试。
Hibernate关联关系映射.CHM Hibernate文档相关
hibernate关联关系简单项目,也可以只运行Java文件不用JSP页面,运用MySQL
关于对Hibernate关联映射的一个总结,其中有各种映射的例子,详细用法 等
Hibernate关联关系映射实例速查,帮助初学者学习。
Hibernate关联映射.doc
hibernate关联关系多对一实例