千家信息网

Hibernate关联关系怎么实现

发表于:2024-11-26 作者:千家信息网编辑
千家信息网最后更新 2024年11月26日,这篇文章主要介绍"Hibernate关联关系怎么实现",在日常操作中,相信很多人在Hibernate关联关系怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Hib
千家信息网最后更新 2024年11月26日Hibernate关联关系怎么实现

这篇文章主要介绍"Hibernate关联关系怎么实现",在日常操作中,相信很多人在Hibernate关联关系怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Hibernate关联关系怎么实现"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一, 一对多的单向关联关系

[@more@]

首先先建立CustomerOrder类,代码如下:

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();

}

}

CustomerOrder类的配置文件分别是Customer.hbm.xmlOrder.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 >

id>

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 >

id>

property>

name="customer"

column="CUSTOMER_ID"

class="mypack.Customer"

not-null="true"

/>

class>

hibernate-mapping>

Order.hbm.xml<many-to-one>元素建立了CustomerORDERS表的外键CUSTOMER_ID之间

的映射。

它包括如下属性。

name:设定待映射的持久化类的属性名,此处为Order类的customer属性。

column:设定和持久化类的属性对应的表的外键,此处为ORDERS表的外键CUSTOMER_ID

class:设定持久化类的属性的类型,此处设定customer属性为Customer类。

notnull:如果为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)方法之前,order1customer对象都是临时对象,临时对象就是刚刚用new创建出来,但是还没有持久会的对象,而Hibernate不会自动持久化order1关联的customer对象,在数据库中意味着仅仅向ORDERS表中插入了一条记录,并且该记录的CUSTOMER_ID字段为null,违反了数据库完整性约束,因为不允许ORDERS表的CUSTOMER_ID字段为null

从上面的例子可以看出当Hibernate持久化一个临时对象时,在默认情况下,它不会自动持久化所关联的其他临时对象,所以会抛出PropertyValueException异常。如果希望当Hibernate持久化Order对象时自动持久化所关联的Customer对象,可以把<many-to-one>cascade属性设为"saveupdate"cascade属性默认为"none"

name="customer"

column="CUSTOMER_ID"

class="mypack.Customer"

cascade"saveupdate"

not-null="true"

/>

这样就能够在Hibernate持久化Order对象时自动持久化所关联的Customer对象了。

二, 一对多的双向关联关系

我们依然使用前面的CustomerOrder的例子,由于是双向关联,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 >

name="orders"

cascade="save-update"

>

</hibernate-mapping>

<set>元素还包含两个子元素:<key><one-to-many><one-to-many>元素设定所关联的持久化类,此处为Order类,<key>元素设定与所关联的持久化对应的表的外键,此处为ORDERS表的CUSTOMERS_ID字段。

它包括如下属性:

元素表明Customer类的orders属性为java.util.Set集合类型。

表明orders集合中存放的是一组Order对象。

属性表明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"

>

set>

因此在映射一对多双向关联关系时,应该在"one"方把inverse属性设为"ture",这样可以提高性能。

三,一对多双向自身关联关系

以食品为例,它代表商品类别,存在一对多双向自身关联关系。如下图所示,水果类别属于食品类别,同时它又包含两个子类别:苹果类别和桔子类别。

图中每一种商品代表一个Category对象,这些对象形成了树型数据结构。每个Category到此,关于"Hibernate关联关系怎么实现"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0