Hibernate 一对多关系映射
1 为什么要学习多表映射?
答案:在实际开发中,我们数据库的表难免会有相互的关联关系,在操作表的时候就有可能会涉及到多张表的操作。例如:一个商城项目中商品和分类,用户和订单,订单和商品的关系等等。
通过之前文章对Hibernate框架学习,我们知道hibernate实现了ORM的思想,可以让我们通过操作实体类就实现对数据库表的操作。所以接下来学习重点是:掌握配置实体之间的关联关系
。
要想实现多表映射,我们可以使用以下步骤来实现:
- 第一步:首先确定两张表之间的关系。如果关系确定错了,后面做的所有操作就都不可能正确。
- 第二步:在数据库中实现两张表的关系
- 第三步:在实体类中描述出两个实体的关系
- 第四步:配置出实体类和数据库表的关系映射 配置的方式支持注解和XML,我们以注解为重点。
那么请思考:表之间的关系到底有几种呢?
数据库中多表之间存在着三种关系,如图所示。
从上图可以看出,系统设计的三种实体关系分别为:多对多、一对多和一对一关系
。
注意:
一对多关系可以看为两种: 即一对多,多对一。实际开发中常用的关联关系,一对多和多对多。而一对一的情况,在实际开发中比较少见
一对多关系可以看为两种: 即一对多,多对一。实际开发中常用的关联关系,一对多和多对多。而一对一的情况,在实际开发中比较少见
2 Hibernate一对多关系映射
2.1 需求分析
我们采用的示例为客户和订单。
- 客户:指的是一个网站的会员,我们记为A。
- 订单:指的是客户会员在网站下的订单。
- 客户和订单的关系即为一对多。
2.2 一对多表关系建立
在一对多关系中,我们习惯把一的一方称之为主表,把多的一方称之为从表。在数据库中建立一对多的关系,需要使用数据库的外键约束
。
什么是外键?
指的是从表中有一列,取值参照主表的主键,这一列就是外键。
一对多数据库关系的建立,如下图所示:
2.3 建立实体类关系
Customer实体类:
/**
* 客户(一方)
* @author http://www.yiidian.com
*
*/
public class Customer {
private Integer id;
private String name;
private String gender;
//关联订单
private Set<Order> orders = new HashSet<Order>();
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
由于订单是多的一方,在实体类中要体现出,每个订单只能对应一个客户,代码如下:
/**
* 订单(多方)
* @author http://www.yiidian.com
*
*/
public class Order {
private Integer id;
private String orderno;
private String productName;
//关联客户
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOrderno() {
return orderno;
}
public void setOrderno(String orderno) {
this.orderno = orderno;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
}
接下来的问题是如何何通过配置的方式把客户实体的订单Set集合
和订单实体的中Customer对象
与数据库建立起来关系。
2.4 映射配置文件
客户配置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 package="com.yiidian.domain">
<class name="Customer" table="t_customer">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<property name="gender" column="gender"></property>
<!-- 一对多配置 -->
<set name="orders">
<!-- 外键字段名称 -->
<key column="cust_id"></key>
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
订单配置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 package="com.yiidian.domain">
<class name="Order" table="t_order">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="orderno" column="orderno"></property>
<property name="productName" column="product_name"></property>
<!-- 多对一配置 -->
<many-to-one name="customer" class="Customer" column="cust_id"/>
</class>
</hibernate-mapping>
2.5 hibernte.cfg.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!-- 连接数据库的参数 -->
<session-factory>
<!-- 1.连接数据库参数 -->
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="hibernate.connection.url">
jdbc:mysql://localhost:3306/hibernate
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- hibernate方言 -->
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- 2.hibernate扩展参数 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- *.hbm.xml文件 -->
<mapping resource="com/yiidian/domain/Customer.hbm.xml" />
<mapping resource="com/yiidian/domain/Order.hbm.xml" />
</session-factory>
</hibernate-configuration>
2.6 执行一对多保存保存
/**
* 演示Hibernate的一对多关系映射操作
*
* @author http://www.yiidian.com
*
*/
public class Demo {
/**
* 保存操作
*/
@Test
public void test1() {
// 准备数据
// 需求:1个客户 2张订单
Customer cust = new Customer();
cust.setName("小苍");
cust.setGender("女");
Order o1 = new Order();
o1.setOrderno("201709070001");
o1.setProductName("JavaWeb开发详解");
Order o2 = new Order();
o2.setOrderno("201709070002");
o2.setProductName("Spring开发详解");
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
// 建立一对多双向关系
cust.getOrders().add(o1);
cust.getOrders().add(o2);
o1.setCustomer(cust);
o2.setCustomer(cust);
session.save(cust);
session.save(o1);
session.save(o2);
tx.commit();
session.close();
}
}
2.7 运行结果
控制台显示:
Hibernate:
insert
into
t_customer
(name, gender)
values
(?, ?)
Hibernate:
insert
into
t_order
(orderno, product_name, cust_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_order
(orderno, product_name, cust_id)
values
(?, ?, ?)
Hibernate:
update
t_order
set
cust_id=?
where
id=?
Hibernate:
update
t_order
set
cust_id=?
where
id=?
t_customer
表数据:
t_order
表的数据:
热门文章
优秀文章