数据库建表原则,在多的一方添加一个外键列,引用一的一方的主键,例如客户和订单,在订单表中增加客户编号作为外键
一对多,类对象之间的关系,在多的一方添加一个集合
class A {
B b; // 一个A对应一个B
}
class B {
A[] 、List<A>、Set<A> // 一个B 对应很多A
}
以客户与订单关系为例建立映射关系
建立客户类
public class Customer implements Serializable{
private Integer id;
private String name;
private String city;
pprivate Set<Order> orders = new HashSet<Order>();//一个客户对应多个订单
}
Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="rock.lee.bean.Customer" table="customer" catalog="test">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<set name="orders">
<!-- customer表在order表中所生成的外键列 -->
<key column="customer_id"></key>
<one-to-many class="rock.lee.bean.Order" />
</set>
<property name="name" column="name" type="java.lang.String"></property>
<property name="city" column="city" type="java.lang.String"></property>
</class>
</hibernate-mapping>
建立订单类
public class Order implements Serializable{
private Integer id;
private String address;
private Double money;
private Customer customer;//一个订单对应一个客户
}
Order.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="rock.lee.bean.Order" table="orders" catalog="test">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<property name="address" column="address" type="java.lang.String"></property>
<property name="money" column="money" type="double"></property>
<!-- 在orders表中添加customer外键列,column为外键列名 -->
<many-to-one name="customer" class="rock.lee.bean.Customer" column="customer_id"></many-to-one>
</class>
</hibernate-mapping>
在hibernate.cfg.xml中配置加载Custoemr和Order映射文件
<mapping resource="rock/lee/bean/Customer.hbm.xml" />
<mapping resource="rock/lee/bean/Order.hbm.xml" />
案例一:保存Customer、Order
@Test
public void testOneToMany01() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer c= new Customer("小明", "BJ");
Order order1 = new Order("二环", 11D);
Order order2 = new Order("三环", 22D);
order1.setCustomer(c);//订单关联客户
order2.setCustomer(c);
c.getOrders().add(order1);//客户关联订单
c.getOrders().add(order2);
session.save(c);
session.save(order1);
session.save(order2);
transaction.commit();
session.close();
}
根据控制台打印的SQL,在insert Customer和Order后会update orders表中的外键列
Hibernate:
update
test.orders
set
customer_id=?
where
id=?
程序分别保存了customer和order,如果只保存customer不保存order会抛出异常
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: rock.lee.bean.Order
在Session关闭后,Hibernate不允许一个peristient状态对象关联一个tranient状态对象
案例二:级联保存
保存customer的同时自动保存order,修改customer类的映射文件增加casecade属性
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="rock.lee.bean.Customer" table="customer" catalog="test">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<set name="orders" cascade="save-update">
<!-- customer表order是中所生成的外键列 -->
<key column="customer_id"></key>
<one-to-many class="rock.lee.bean.Order" />
</set>
<property name="name" column="name" type="java.lang.String"></property>
<property name="city" column="city" type="java.lang.String"></property>
</class>
</hibernate-mapping>
只保存customer,不保存order
@Test
public void testOneToMany02() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer c= new Customer("小明", "BJ");
Order order1 = new Order("二环", 11D);
Order order2 = new Order("三环", 22D);
order1.setCustomer(c);//订单关联客户
order2.setCustomer(c);
c.getOrders().add(order1);//客户关联订单
c.getOrders().add(order2);
session.save(c);
transaction.commit();
session.close();
}
配置了casecade后当一个persistent对象关联了一个traniesent对象是会自动保存关联的那个transient对象
案例三:对象导航
案例四:级联删除
@Test
public void testOneToMany03() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer c = (Customer) session.get(Customer.class, 1);
session.delete(c);
transaction.commit();
session.close();
}
删除customer时会先把order表中的外键列customer_id设置为null,在删除customer
Hibernate:
update
test.orders
set
customer_id=null
where
customer_id=1
Hibernate:
delete
from
test.customer
where
id=1
删除orders表中的数据时直接删除,因为没有外键依赖关系
修改Customer.hbm.xml配置文件,增加级联删除配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="rock.lee.bean.Customer" table="customer" catalog="test">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<set name="orders" cascade="save-update,delete">
<!-- customer表order是中所生成的外键列 -->
<key column="customer_id"></key>
<one-to-many class="rock.lee.bean.Order" />
</set>
<property name="name" column="name" type="java.lang.String"></property>
<property name="city" column="city" type="java.lang.String"></property>
</class>
</hibernate-mapping>
此时删除customer对象时,也将删除order对象,级联删除,仍然是先接触外键关系,在删除数据,如果删除一个detached状态的customer对象无法级联删除的
修改Order.hbm.xml文件,将外键设置为非null
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="rock.lee.bean.Order" table="orders" catalog="test">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<property name="address" column="address" type="java.lang.String"></property>
<property name="money" column="money" type="double"></property>
<!-- 在orders表中添加customer外键列,column为外键列名 -->
<many-to-one name="customer" class="rock.lee.bean.Customer" column="customer_id" not-null="true"></many-to-one>
</class>
</hibernate-mapping>
此时,当删除Customer对象是无法级联删除Order,因为删除前需要先接触外键,设置orders表中customer_id为null,但由于配置了not-null="true"属性会抛出异常
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'customer_id' cannot be null
这种情况只能先删除orders表中的订单数据,在删除customer表中的数据,业务上不会有此种情况,删个订单还把客户干掉了
案例五:孤儿删除
在一对多关系中,表的建立存在父子表,customer为父表,orders为子表,当一个customer和一个order解除关系后,作为order信息实际上就不完整了,不会有一个订单不关联任何用户的情况
修改Customer.hbm.xml,在casecade属性中增加delete-orphan
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="rock.lee.bean.Customer" table="customer" catalog="test">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<set name="orders" cascade="save-update,delete,delete-orphan" >
<!-- customer表order是中所生成的外键列 -->
<key column="customer_id"></key>
<one-to-many class="rock.lee.bean.Order" />
</set>
<property name="name" column="name" type="java.lang.String"></property>
<property name="city" column="city" type="java.lang.String"></property>
</class>
</hibernate-mapping>
不调用deleet(),只接触cusomter与order之间的关系
@Test
public void testOneToMany04() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer c1 = (Customer) session.get(Customer.class, 1);
Order o1 = (Order) session.get(Order.class, 1);
c1.getOrders().remove(o1);//解除客户与订单关系
transaction.commit();
session.close();
}
Hibernate会先接触外键关系,在删除
Hibernate:
update
test.orders
set
customer_id=null
where
customer_id=?
and id=?
Hibernate:
delete
from
test.orders
where
id=?
casecade取值:
casecade取值来源JPA规范,但Hibernate对JPA进行了扩展
有红点的是Hibernate扩展的,其它是JPA
inverse单相关系维护:
数据库数据
mysql> select * from customer;
+----+--------+------+
| id | name | city |
+----+--------+------+
| 1 | 孙艺珍 | BJ |
| 2 | 林允儿 | SH |
+----+--------+------+
2 rows in set (0.00 sec)
mysql> select * from orders;
+----+---------+-------+-------------+
| id | address | money | customer_id |
+----+---------+-------+-------------+
| 1 | 二环 | 11 | 1 |
+----+---------+-------+-------------+
1 row in set (0.00 sec)
将order表中1号订单与林允儿关联
@Test
public void testOneToMany06() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Order o = (Order) session.get(Order.class, 1);
Customer lyr = (Customer) session.get(Customer.class, 2);
o.setCustomer(lyr);
lyr.getOrders().add(o);
transaction.commit();
session.close();
}
控制台会有两条update语句,更新orders表中的外键列
Hibernate:
update
test.orders
set
address=?,
money=?,
customer_id=?
where
id=?
Hibernate:
update
test.orders
set
customer_id=?
where
id=?
原因是Session中的缓存与快照比对后发现不一样所有cusotmer和order都去更新orders表中的外键列
修改Customer.hbm.xml增加inverse="true"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="rock.lee.bean.Customer" table="customer" catalog="test">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<set name="orders" cascade="save-update,delete,delete-orphan" inverse="true" >
<!-- customer表order是中所生成的外键列 -->
<key column="customer_id"></key>
<one-to-many class="rock.lee.bean.Order" />
</set>
<property name="name" column="name" type="java.lang.String"></property>
<property name="city" column="city" type="java.lang.String"></property>
</class>
</hibernate-mapping>
同样的操作,只有一条update,有order发出,在Cusomter.hbm.xml配置invers="true" 表示关联关系的控制权被反转了,交由order控制
Customer customer = new Customer();// 定义一个客户
customer.setName("张三");
Order order = new Order();// 定义一个订单
order.setMoney(2000d);
order.setAddr("二环");
// 建立对象之间关系
customer.getOrders().add(order); // 客户对象关联订单
session.save(customer);
custoemr和order都会被保存,但orders表中cusotmer_id列为null,因为维护外键的权利由order控制,但保存了cusomter时级联保存order,却没有维护外键的权利,所以orders表中的外键列为null
- 大小: 65.6 KB
- 大小: 319.3 KB
分享到:
相关推荐
在本篇博文中,我们将深入探讨Hibernate框架中的一个重要特性——一对一(One-to-One)关系映射。Hibernate作为Java领域中最流行的ORM(对象关系映射)工具,它允许开发者以面向对象的方式处理数据库操作,简化了...
- Hibernate支持多种关系映射,本章将深入讲解一对一、一对多和多对一的关系配置,包括集合类型的选择(List, Set, Map等)和级联操作的设置。 4. **Chapter 9:多对多关系映射** - 多对多关系在数据库设计中常见...
- Chapter16可能深入讲解了一对一和一对多关联的映射与操作。 - Chapter17至19可能涉及了多对多关系的处理,以及在实际应用中的注意事项。 - Chapter21和22可能探讨了更复杂的查询技术,如子查询、连接查询和分页...
在后续的章节中,`appendixA`、`appendixB`和`appendixC`可能是对特定主题的补充,如 Hibenate的缓存机制、多对一、一对多、多对多的关系映射,或者更高级的主题,如懒加载、级联操作、自定义类型等。这些内容对于...
第7章 映射一对多关联关系 7.1 建立多对一的单向关联关系 7.1.1 元素的not-null属性 7.1.2 级联保存和更新 7.2 映射一对多双向关联关系 7.2.1 元素的inverse属性 7.2.2 级联删除 7.2.3 父子关系 7.3...
本章介绍一对多关联关系的映射方法,重点介绍inverse属性和cascade属性的用法。本章还将介绍通过Hibernate API来保存、修改和删除具有关联关系的对象的方法。 7.1 建立多对一的单向关联关系 148 7.1.1 [many-to-...
5. **多对多关系映射**:详述如何配置和处理多对多关联,包括中间表的管理,以及集合的懒加载和级联操作。 6. **一对一关系映射**:深入讨论一对一关系的配置,包括外键约束、主键共享以及一对一关系的级联操作。 ...
本章介绍一对多关联关系的映射方法,重点介绍inverse属性和cascade属性的用法。本章还将介绍通过Hibernate API来保存、修改和删除具有关联关系的对象的方法。 7.1 建立多对一的单向关联关系 148 7.1.1 [many-to-...
- **关联映射**:深入探讨了一对一、一对多、多对多等各种关联关系的映射方法。 - **继承映射**:讨论了单表继承、类表继承和子类表继承等多种继承映射策略。 - **查询语言**:介绍了Hibernate Query Language (HQL)...
4. **Associations**:关联映射处理一对多、多对多等关系类型,支持不同类型的关联映射策略。 5. **Composite Components**:复合组件允许将复杂的Java对象映射到数据库中,例如将地址对象映射为一个表中的多个字段...
第7章 映射一对多关联关系 7.1 建立多对一的单向关联关系 7.1.1 元素的not-null属性 7.1.2 级联保存和更新 7.2 映射一对多双向关联关系 7.2.1 元素的inverse属性 7.2.2 级联删除 7.2.3 父子关系 7.3...
第7章 映射一对多关联关系 7.1 建立多对一的单向关联关系 7.1.1 元素的not-null属性 7.1.2 级联保存和更新 7.2 映射一对多双向关联关系 7.2.1 元素的inverse属性 7.2.2 级联删除 7.2.3 父子关系 7.3...
第7章 映射一对多关联关系 7.1 建立多对一的单向关联关系 7.1.1 元素的not-null属性 7.1.2 级联保存和更新 7.2 映射一对多双向关联关系 7.2.1 元素的inverse属性 7.2.2 级联删除 7.2.3 父子关系 7.3...
3. 实体类与对象关系映射:讲解如何定义Java实体类,并使用注解或XML文件进行对象关系映射,包括基本类型映射、关联映射(一对一、一对多、多对一、多对多)和继承映射。 4. Session与Transaction:介绍Hibernate的...
6. **关联映射**:Hibernate支持一对一、一对多、多对一、多对多等各种关联关系的映射,方便处理复杂的数据库关系。 然而,压缩包内的文件名称列表似乎包含了与Hibernate无关的文件,如“我和一个偷吃禁果的女孩的...
- **关联映射**:支持多种关联类型(一对一、一对多、多对一、多对多),使得数据库表之间的复杂关系可以方便地在Java对象中表达。 总结来说,Hibernate 3.3.2作为一款成熟的ORM框架,极大地简化了Java应用中的...
- **多对多关联**:介绍如何在Hibernate中实现多对多关联,并给出具体的配置示例。 - **继承映射**:探讨如何使用单表、多表和联合表继承模式来映射具有层次结构的实体。 6. **事务管理** - **本地事务**:讨论...
3. **映射文件详解**:详细讲解XML或注解方式的实体映射,包括属性映射、关系映射(一对一、一对多、多对多)、继承映射等。 4. **HQL(Hibernate Query Language)**: Hibernate自己的查询语言,类似于SQL,但更...
4. **实体关系映射**:详述了如何配置和管理实体类之间的多对一、一对一、多对多关系,以及集合类型的映射。 5. **缓存机制**:讨论了Hibernate的缓存层次结构,包括一级缓存(Session缓存)和二级缓存...