文章目录
Hibernate 的框架概述
什么是框架
框架,指的是软件半成品,已经完成了部分功能。
EE 的三层架构
Hibernate 概述
一个持久层的 ORM 框架。
什么是 ORM
ORM : object relation mapping(对象关系映射)。指的是将一个 Java 中的对象与关系型数据库中的表建立一种映射关系,从而操作对象就可以操作数据库中的表。
创建第一个 Hibernate 程序
下载 Hibernate 的开发环境
解压 Hibernate
- documentation 【Hibernate 开发文档】
- lib
- required 【Hibernate 开发的必须依赖包】
- optional 【Hibernate 开发的可选 jar 包】
- project 【Hibernate 提供的项目】
创建一个项目,引入 jar 包
- 数据库驱动包
- Hibernate 开发必须的 jar 包
- Hibernate 开发的日志记录包
创建表
CREATE TABLE `cst_customer` (
`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
`cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
`cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
`cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
`cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
`cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
`cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
创建实体类
public class Customer {
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_phone;
private String cust_mobile;
创建映射(******)
映射需要通过一个 xml 的配置文件来完成,这个配置文件可以任意命名,但是尽量统一命名规范(类名.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="hibernate_demo1.Customer" table="cst_customer">
<!--建立类中的属性与表中的逐渐对应-->
<id name="cust_id" column="cust_id">
<generator class="native"/>
</id>
<!--建立类中的普通属性和表的字段的对应-->
<property name="cust_name" column="cust_name"/>
<property name="cust_source" column="cust_source"/>
<property name="cust_industry" column="cust_industry"/>
<property name="cust_level" column="cust_level"/>
<property name="cust_phone" column="cust_phone"/>
<property name="cust_mobile" column="cust_mobile "/>
</class>
</hibernate-mapping>
创建一个 Hibernate 的核心配置文件(******)
Hibernate 核心配置文件的名称:hibernate.cfg.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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>
<!--连接数据库的基本参数-->
<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">1183787376</property>
<!--配置Hibernate 的方言-->
<!--可选配置===============-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!--打印sql-->
<property name="hibernate.show_sql">true</property>
<!--格式化sql-->
<property name="hibernate.format_sql">true</property>
<mapping resource="hibernate_demo1/Customer.hbm,xml"/>
</session-factory>
</hibernate-configuration>
Hibernate 映射的配置
映射的配置
- class 标签的配置
- 标签用来建立类与表的映射关系
- 属性
- 【name】类的全路径
- 【table】表名
- 【catalog】数据库名
- id 标签的配置
- 用来建立类中的属性与表中的主键的对应关系
- 属性
- 【name】类中的属性
- 【column】标中的字段,当自动建表时使用
- 【length】
- 【type】
- property 标签的配置
- 用来建立类中的普通属性与标中字段的对应关系
- 属性
- 【name】类中的属性
- 【column】表中的字段,当自动建表时使用
- 【length】长度
- 【type】
- 【not-null】设置非空
- 【unique】设置唯一
Hibernate 核心配置
Hibernate 核心配置方式
- 属性文件方式
- xml 文件方式
核心配置
- 必须的配置
- 驱动类
- url 路径
- 用户名
- 密码
- 可选的配置
- 显示 SQL : hibernate.show.sql
- 格式化 SQL : hibernate.format.sql
- 自动建表:hibernate.hbm2ddl.auto
- 【none】:不使用 hibernate 的自动建表
- 【create】:如果数据库中已经有表,删除原表,重新创建表;如果没有表,新建表
- 【create-drop】:如果数据库中已经有表,删除原表
- 【update】:如果数据库中有表,使用原有表,如果没有表,创建新表(更新表结构)
- 【validate】:如果没有表,不会创建表,只会使用数据库中原有的表(但会校验映射和表结构是否一致)
- 映射文件的引入
- 引入映射文件的位置
Session
类似 Connection 对象是连接对象。Session 代表的是 Hibernate 与数据库连接对象,不是线程安全的,所以不能定义成全局的,是与数据库交互的桥梁。
Session 中的 API
保存方法:
Serializable save(Object obj)【此方法返回保存的那条记录的id】
- 查询方法:
T get(Class c, Serializable id)
T load(Class c, Serializable id)
get 方法和 load 方法的区别?
@Test
//查询客户
public void demo3(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
/*
* get方法
* 采用的是立即加载,执行到这一行代码的时候,就会马上发送SQL语句去执行
* 查询后返回的是真实对象本身
* 查询一个找不到的对象,返回null
* load方法
* 采用的延迟加载(lazy懒加载),执行到这行代码的时候不会发送SQL语句,当真正使用这个对象的时候才会发送SQL语句
* 查询后返回的是代理对象
* 查询一个找不到的对象的时候返回ObjectNotFoundException
* */
//编写代码
//使用get方法查询
Customer customer = session.get(Customer.class, 2l);
System.out.println(customer);
//使用load方法查询
Customer customer1 = session.load(Customer.class, 2l);
System.out.println(customer);
tx.commit();
session.close();
}
修改方法
void update(Object obj)
@Test
public void demo3(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//第一种,直接创建对象,进行修改
Customer customer = new Customer();
customer.setCust_id(1l);
customer.setCust_name("王聪");
session.update(customer);
//第二种,先查询,再修改
Customer customer1 = session.get(Customer.class, 2l);
customer1.setCust_name("王小贱");
session.update(customer1);
tx.commit();
session.close();
}
删除方法
void delete(Object obj)
@Test
public void demo4(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//直接创建对象删除
Customer customer = new Customer();
customer.setCust_id(1l);
session.delete(customer);
//先查询,再删除(推荐)--级联删除
Customer customer2 = session.get(Customer.class, 4l);
session.delete(customer2);
tx.commit();
session.close();
}
保存或更新
void saveOrUpdate(Object obj)
查询所有
@Test
//查询所有
public void demo5(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//接收HQL: Hibernate Query Language 面向对象的查询语言
Query query = session.createQuery("from Customer");
List<Customer> list = query.list();
for(Customer customer : list){
System.out.println(customer);
}
//接收SQL
SQLQuery query1 = session.createSQLQuery("select * from cst_customer");
List<Object[]> list = query1.list();
for (Object[] objects: list) {
System.out.println(Arrays.toString(objects));
}
tx.commit();
session.close();
}
Transcation:事务对象
Hibernate 中管理事务的对象。
- commit()
- rollback()
持久化类编写的规则
持久化类的概述
什么是持久化类
持久化:将内存中的一个对象持久化到数据库中的过程。Hibernate 框架就是用来进行持久化的框架。
持久化类:一个 Java 对象与数据库的表建立了映射关系,那么这个类在 Hibernate 中称为持久化类。持久化类 = Java 类 + 映射文件
持久化类的编写规则
- 对持久化类提供一个无参的构造方法:Hibernate 底层需要使用反射生成实例
- 属性需要私有,对私有属性提供 public 的 get 和 set 方法:Hibernate 中获取,设置对象的值
- 对持久化类提供一个唯一的表示 OID 与数据库主键对应:在 Hibernate 中通过持久化类的 OID 的属性来区分是否是统一个属性
- 持久化类中属性尽量使用包装类类型:因为基本数据类型默认是 0 ,那么 0 会有很多歧义,这样不知到在数据库中插入的值是默认的 0 ,还是插入的值是 0 。包装类类型默认值是 null,容易和 0 去区分。
- 持久化类不要使用 final 修饰:延迟加载本身是 hibernate 一个优化手段,返回的是一个代理对象。如果不能被继承,不能产生代理类,延迟加载也就失败,load 方法和 get 方法也就变得一样了。
主键生成策略
主键的分类
自然主键
- 自然主键:主键本身就是表中的一个字段(实体中的一个具体属性)。
- 创建一个人员表,人员都会有一个身份证号(唯一的不可重复),使用身份证号作为主键,这种主键就是称为自然主键,这个主键也是人的一个属性。
代理主键
- 代理主键:主键本身不是表中必须的一个字段(不是实体中某个具体的属性)。
- 创建一个人员表,没有使用人员中的身份证号,用了一个与这个表不相关的字段 ID。这种主键称为代理主键。
- 在实际的开发当中,尽量使用代理主键。
- 一旦主键参与到业务逻辑当中,后期有可能需要修改源代码。
- 好的程序设计满足 OCP 原则,对程序的扩展是 open 的,对修改源码是 close 的。
主键的生成策略
Hibernate 的主键生成策略
在实际开发中,一般不允许用户手动设置主键,一般会将这个主键交给数据库,手动编写程序来进行设置。在 Hibernate 中为了减少程序的编写,提供了多种主键的生成策略。
-
increment :hibernate 中提供的一个自动增长机制,使用于 short、int 和 long 类型的主键。在单线程的程序中使用。
- 首先发送一条语句,select max(id) from 表,然后 id + 1 作为下一条记录的主键,这里就涉及到了线程安全的问题。
-
identity:使用 short、int 和 long 类型的主键,使用数据库底层的自动增长机制。适用于有自动增长机制的数据库,如 MySQL,但是 Oracle 是没有自动增长的。
-
sequence:适用于 short、int 和 long 类型的主键,采用的是序列的方式。(Oracle 支持序列),但是 MySQL 就不支持sequence。
-
uuid:适用于字符串类型主键,使用 hibernate 中的随机的方式生成字符串的主键。
-
native:本地策略,可以在 identity 和 sequence 之间进行自动切换。
-
assigned:hibernate 会放弃外键的管理,需要通过自己手动编写程序或者用户自己设置。
-
foreign:外部的,一对一的一种关联映射的情况下使用。
持久化类的三种状态
Hibernate 是持久层框架,通过持久化类完成 ORM 操作。Hibernate 为了更好的管理持久化类,将持久化类分为三中状态。持久化类 = Java + 映射
瞬时态
- 这种对象没有唯一的标识 OID ,没有被 session 管理,称为瞬时态对象。
持久态(******)
- 这种对象有唯一标识 OID,被 session 管理,称为持久态对象。持久化对象的持久态对象,可以自动更新数据库。
脱管态
- 这种对象有唯一标识 OID,没有被 session 管理,称为脱管态。
区分这三种状态的对象
public class HibernateDemo2 {
@Test
//三种状态的区分
public void demo1(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();//瞬时态对象,没有唯一的标识OID,没有被session管理
customer.setCust_name("王瓜");
Serializable id = session.save(customer);//持久态对象,有唯一的标识OID,被session管理
session.get(Customer.class, id);
transaction.commit();
session.close();
System.out.println("客户名称:" + customer.getCust_name());//脱管态对象,有唯一的标识OID,没有被session管理
}
}
持久化类的状态转换
瞬时态对象
- 获得
Customer customer = new Customer();
- 状态转换
- 瞬时 > 持久 【sava(Object obj) 、saveOrUpdate(Object obj)】
- 瞬时 > 脱管 【customer.setCust_id(1l)】
持久态对象
- 获得
- get()、load()、find()、iterate()
- 状态转换
- 持久 > 瞬时 【delete()】
- 持久 > 脱管 【close()、clear()、evict(Object obj)】
脱管态对象
- 获得
Customer customer = new Customer(); customer.setCust_id(2l);
- 状态转换
- 脱管 > 持久 【update(Object obj)、saveOrUpdate()】
- 脱管 > 瞬时 【customer.setCust_id(null)】
Hibernate 的一级缓存
什么是缓存
缓存:是一种优化的方式,将数据存入到内存当中,使用的时候直接从缓存中获取,不用通过存储源。
Hibernate 的一级缓存
Hibernate 框架中提供了优化手段,缓存、抓取策略。Hibernate 中提供了两种缓存机制:一级缓存,二级缓存。
Hibernate 的一级缓存:称为 Session 级别的缓存,一级缓存的生命周期与 Session 一致(一级缓存是由 Session 中的一系列的 Java 集合构成)。一级缓存是自带的不可卸载的。(Hibernate 的二级缓存是 SessionFactory 级别的,需要配置的缓存)
证明一级缓存的存在
public class HibernateDemo3 {
@Test
//证明一级缓存的存在
public void demo1(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
//第一种证明方法
Customer customer1 = session.get(Customer.class, 1l);//发送SQL语句,get方法首先会从缓存中找这个对象,缓存中不存在,所以需要从数据库中寻找,这是发送SQL语句
System.out.println(customer1);
Customer customer2 = session.get(Customer.class, 1l);//不发送SQL语句,因为缓存中存在了这个对象,所以不发送SQL语句
System.out.println(customer2);
//第二种证明方法
Customer customer = new Customer();
customer.setCust_name("小峰");
Serializable id = session.save(customer);
session.get(Customer.class, id);
transaction.commit();
session.close();
}
}
Hibernate 的一级缓存的结构
一级缓存中特殊区域:快照区
将你放入到一级缓存区域的这个数据进行一个快照(就是把这个数据又备份了一份),当你的数据发生变化的时候,当你的事务要提交的时候,它会拿你一级缓存区的数据和快照区的数据做一个比较,如果数据不一样就会自动更新数据库,如果一样就不更新数据库了。
Hibernate 事务管理
事务的回顾
- 事务:事务指的是逻辑上的一组操作,组成这组操作的各个逻辑单元,要么全都成功,要么全都失败。
- 事务的特性
- 原子性:代表不分割
- 一致性:代表事务执行的前后,数据的完整性保持一致
- 持久性:代表事务执行完成后,数据就持久数据库当中了
- 隔离性:代表一个事务在执行的过程当中,不应该受到其他事务的干扰
如果不考虑隔离性,引发安全性问题
- 读问题
- 脏读:一个事务读到另一个事务未提交的数据
- 不可重复读:一个事务读到另一个事务已经提交的 update 的数据,导致在前一个事务多次查询结果不一致
- 幻读:一个事务读到另一个事务已经提交的 insert 的数据,导致在前一个事务多次查询结果不一致
- 写问题
读问题的解决
- 设置事物的隔离级别
- Read uncommitted:以上问题都有可能发生
- Read comitteed:解决脏读问题,但是不可重复读和幻读有可能发生
- Repeatable read:解决脏读和不可重复读,但是幻读有可能发生
- Serializble:解决所有读问题
Hibernate 一对多关联映射
数据库表与表之间的关系
一对多的关系
- 什么样的关系是一对多?
一个部门对于多个员工,一个员工只能属于一个部门。 - 一对多建表原则
在多的一方创建外键指向一的一方的主键
多对多的关系
- 什么样的关系属于多对多?
一个学生可以选择多门课程,一门课程也可以被多个学生选择。
一个用户可以选择多个角色,一个角色可以被多个用户选择。 - 多对多建表原则
创建一个中间表,中间表至少有两个字段分别作为外键指向多对多双方的主键。
一对一的关系
- 什么样的关系属于一对一?
一个公司只能有一个注册地址,一个地址只能有一个公司注册。
Hibernate 一对多关系配置
创建一个项目,引入 jar 包
创建数据库和表
- 客户表
CREATE TABLE `cst_customer` (
`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
`cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
`cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
`cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
`cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
`cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
`cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
- 联系人表
CREATE TABLE `cst_linkman` (
`lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
`lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名',
`lkm_cust_id` bigint(32) NOT NULL COMMENT '客户id',
`lkm_gender` char(1) DEFAULT NULL COMMENT '联系人性别',
`lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话',
`lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机',
`lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱',
`lkm_qq` varchar(16) DEFAULT NULL COMMENT '联系人qq',
`lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位',
`lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注',
PRIMARY KEY (`lkm_id`),
KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),
CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
创建实体
- 一的一方的实体
/**
* 客户实体
*/
public class Customer {
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_phone;
private String cust_mobile;
//如何表示一个客户里有多个联系人?
//通过ORM的方式表示:一个客户对应多个联系人
//放置的是多的一方的集合,Hibernate默认使用的是Set集合
private Set<LinkMan> linkMans = new HashSet<LinkMan>();
- 多的一方的实体
public class LinkMan {
private Long lkm_id;
private String lkm_name;
private String lkm_gender;
private String lkm_phone;
private String lkm_mobile;
private String lkm_email;
private String lkm_qq;
private String lkm_position;
private String lkm_memo;
//通过ORM的方式表示:一个联系人只能属于某一个客户
//放置的是一的一方的对象
private Customer customer;
创建映射文件
多的一方的映射的创建
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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="domain.LinkMan" table="cst_linkman">
<!--建立OID与主键的映射-->
<id name="lkm_id" column="lkm_id">
<generator class="native"/>
</id>
<!--建立普通属性与表字段的映射-->
<property name="lkm_name"/>
<property name="lkm_gender"/>
<property name="lkm_phone"/>
<property name="lkm_mobile"/>
<property name="lkm_email"/>
<property name="lkm_qq"/>
<property name="lkm_position"/>
<property name="lkm_memo"/>
<!--配置多对一的关系:放置一的一方的对象
* name:一的一方的对象的属性名称
* class:一的一方的类的全路径
* column:在多的一方的外键的名称
-->
<many-to-one name="customer" class="domain.Customer" column="lkm_cust_id"></many-to-one>
</class>
</hibernate-mapping>
一的一方的映射的创建
<?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="domain.Customer" table="cst_customer">
<!--建立OID与主键的映射-->
<id name="cust_id" column="cust_id">
<generator class="native"/>
</id>
<!--建立普通属性与数据库表的字段的映射-->
<property name="cust_name"/>
<property name="cust_source"/>
<property name="cust_industry"/>
<property name="cust_level"/>
<property name="cust_phone"/>
<property name="cust_mobile"/>
<!--配置一对多的映射:放置多的一方的对象的集合
set 标签:
*name:放的是多的一方的对象的集合属性名称-->
<set name="linkMans">
<!--key标签
*colunm:多的一方的外键的名称-->
<key column="lkm_cust_id"/>
<!--one-to-many标签
*class:多的一方的类的全路径-->
<one-to-many class="domain.LinkMan"/>
</set>
</class>
</hibernate-mapping>
编写测试类
public class HibernateDemo1 {
@Test
//保存两个客户和三个联系人并且建立好关系
public void demo1(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();//开启事务
//创建两个客户
Customer customer1 = new Customer();
customer1.setCust_name("王东");
Customer customer2 = new Customer();
customer2.setCust_name("赵红");
//创建三个联系人
LinkMan linkMan1 = new LinkMan();
linkMan1.setLkm_name("如花");
LinkMan linkMan2 = new LinkMan();
linkMan2.setLkm_name("凤姐");
LinkMan linkMan3 = new LinkMan();
linkMan3.setLkm_name("旺财");
//设置关系
linkMan1.setCustomer(customer1);
linkMan2.setCustomer(customer1);
linkMan3.setCustomer(customer2);
customer1.getLinkMans().add(linkMan1);
customer1.getLinkMans().add(linkMan2);
customer2.getLinkMans().add(linkMan3);
//保存数据
session.save(linkMan1);
session.save(linkMan2);
session.save(linkMan3);
session.save(customer1);
session.save(customer2);
tx.commit();//提交事务
session.close();//结束事务
}
}
Hibernate 一对多相关操作
一对多关系只保存一边
不可以
一对多的级联操作
级联:操作一个对象的时候,是否会操作其关联的对象
级联是有方向性的:操作一的一方的时候是否操作到多的一方;操作多的一方的时候是否操作到多的一方
级联保存或更新
- 保存客户级联联系人
@Test
//保存两个客户和三个联系人并且建立好关系
public void demo2(){
/**
* 级联保存或更新操作
* 保存客户级联联系人
* 操作的主体是客户对象,那么就要在客户的映射文件中进行配置
* <set name="linkMans" cascade="save-update">
*/
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();//开启事务
//创建两个客户
Customer customer = new Customer();
customer.setCust_name("王东");
//创建三个联系人
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("如花");
//设置关系
linkMan.setCustomer(customer);
customer.getLinkMans().add(linkMan);
//保存数据
session.save(customer);
tx.commit();//提交事务
session.close();//结束事务
}
<!--配置一对多的映射:放置多的一方的对象的集合
set 标签:
*name:放的是多的一方的对象的集合属性名称
*cascade:级联保存-->
<set name="linkMans" cascade="save-update">
<!--key标签
*colunm:多的一方的外键的名称-->
<key column="lkm_cust_id"/>
<!--one-to-many标签
*class:多的一方的类的全路径-->
<one-to-many class="domain.LinkMan"/>
</set>
- 保存联系人级联客户
<many-to-one name="customer" cascade="save-update" class="domain.Customer" column="lkm_cust_id"/>