Hibernate中的一对多单向关联
意思是:一方可以看到多方,多方看不到一方
实例:国家与城市——国家为1,城市为n

一、基本概念

域属性:对象自身的属性
关联属性:关联关系的属性
有Country(国家)和City(城市)两个实体
在国家实体中,countryName、countryID为域属性,citys为关联属性
Hibernate中的一对多单向关联_hibernate
关联方向——分为单向和双向
单向关联:只在一方把另一方作为关联属性,即只有一个实体对象可以加载和访问对方
Country中有citys,而City中没有country;
双向关联:彼此把对方设为关联属性,彼此都可以加载和访问
Country中有citys,City中也有country;
关联关系的维护:
关联关系在Java代码上的维护:
Hibernate中的一对多单向关联_xml_02
关联关系在数据库上的维护:
本质上是对外键值的维护,当少的一方维护关系时
Hibernate中的一对多单向关联_xml_03
当多的一方维护关系时:
Hibernate中的一对多单向关联_外键_04
总结一下就是session.save(1)维护外键关系的是update语句,session.save(n)维护外键关系的是insert语句

牢记一点,Java代码谁在维护关联关系,session就save谁

1)实体类(1、Country )

package com.hibernate.beans;

import java.util.HashSet;
import java.util.Set;

public class Country {
//域属性
private Integer countryId;
private String countryName;
//关联属性
private Set<City> citys;
public Country() {
citys = new HashSet<City>();
}
public Country(String countryName) {
this();
this.countryName = countryName;
}

public Integer getCountryId() {
return countryId;
}
public void setCountryId(Integer countryId) {
this.countryId = countryId;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
@Override
public String toString() {
return "Country [countryId=" + countryId + ", countryName="
+ countryName + "]";
}
public Set<City> getCitys() {
return citys;
}
public void setCitys(Set<City> citys) {
this.citys = citys;
}


}

2)实体类(2、City)

package com.hibernate.beans;

public class City {

private Integer cityId;
private String cityName;
public City() {
}

public City(String cityName) {
this.cityName = cityName;
}

public Integer getCityId() {
return cityId;
}

public void setCityId(Integer cityId) {
this.cityId = cityId;
}

public String getCityName() {
return cityName;
}

public void setCityName(String cityName) {
this.cityName = cityName;
}


@Override
public String toString() {
return "City [cityId=" + cityId + ", cityName=" + cityName
+ "]";
}

}

3)映射文件(Country.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.hibernate.beans">
<class name="Country" table="t_country">
<!-- 域属性的映射 -->
<id name="countryId" column="t_countryId">
<!-- 主键生成策略 -->
<generator class="native"></generator>
</id>
<property name="countryName" column="t_countryName"></property>
<!-- 关联属性的映射 -->
<set name="citys" cascade="save-update"><!-- save-update级联保存 -->
<!-- 一方主键对应在多方表的外键名 -->
<key column="t_countryId"></key>
<!-- 多方的类型 -->
<one-to-many class="City"/>
</set>
</class>
</hibernate-mapping>

4)映射文件(City.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.hibernate.beans">
<class name="City" table="t_city">
<id name="cityId" column="t_cityId">
<!-- 主键生成策略 -->
<generator class="native"></generator>
</id>
<property name="cityName" column="t_cityName"></property>
</class>
</hibernate-mapping>

5)主映射文件(Hibernate.hbm.xml)

测试方法:

public void test() {
// 获取连接
Session session = HbnUtils.getSession();
try {
// 开启事务
session.beginTransaction();
Country country = new Country("CN");
City city0 = new City("南昌");
City city1 = new City("武汉");
City city2 = new City("长沙");

country.getCitys().add(city0);
country.getCitys().add(city1);
country.getCitys().add(city2);
// 执行业务
session.save(country);
// 提交事务
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
// 回滚
session.getTransaction().rollback();
}
}

分析运行过程

从控制台日志可以看出Hibernate运行过程

Hibernate: 
insert
into
t_country
(t_countryName)
values
(?)
Hibernate:
insert
into
t_city
(t_cityName)
values
(?)
Hibernate:
insert
into
t_city
(t_cityName)
values
(?)
Hibernate:
insert
into
t_city
(t_cityName)
values
(?)
Hibernate:
update
t_city
set
t_countryId=?
where
t_cityId=?
Hibernate:
update
t_city
set
t_countryId=?
where
t_cityId=?
Hibernate:
update
t_city
set
t_countryId=?
where
t_cityId=?

首先保存了City对象除了外键以外的所有的字段,然后保存Country对象的所有字段,最后根据Country的id去更新City的外键字段
控制台打印顺序并不是Hibernate的执行顺序,执行顺序参考官方文档


如有疑问,欢迎入群讨论:511906138