我们以客户(Customer)与订单(Order)为例

实体类创建

Order订单实体类

//订单-----多的一方
public class Order {private Integer id;private Double money;private String receiverInfo; // 收货地址// 订单与客户关联private Customer c; // 描述订单属于某一个客户public Customer getC() {return c;}public void setC(Customer c) {this.c = c;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}public String getReceiverInfo() {return receiverInfo;}public void setReceiverInfo(String receiverInfo) {this.receiverInfo = receiverInfo;}}

Customer客户实体类

//客户 ------一的一方
public class Customer {private Integer id; // 主键private String name; // 姓名// 描述客户可以有多个订单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;}}

Hbm映射文件编写

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="cn.nwtxxb.oneToMany.Order" table="t_order"><id name="id" column="c_id"><generator class="identity" /></id><property name="money" column="c_money" /><property name="receiverInfo" column="c_receiverInfo" length="50"/><!-- 多对一 --><many-to-one fetch="join" lazy="false" name="c" class="cn.nwtxxb.oneToMany.Customer" column="c_customer_id"></many-to-one><!-- name属性它描述的是Order类中的一的一方的属性名称   Customer c;class 代表一的一方的类型column 描述的是一对多,在多的一方产生的外键的名称 c_customer_id--></class></hibernate-mapping>

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="cn.nwtxxb.oneToMany.Customer" table="t_customer"><id name="id" column="c_id"><generator class="identity" /></id><property name="name" column="c_name" length="20" /><!-- 一个客户关联多个订单 --><set name="orders" inverse="true" cascade="save-update"><key column="c_customer_id" /><one-to-many class="cn.nwtxxb.oneToMany.Order" /></set><!-- 使用set来描述在一的一方中关联的多 Set<Order>,它的name属性就是set集合的名称 key:它主要描述关联的多的一方产生的外键名称,注意要与多的一方定义的外键名称相同 one-to-many 描述集合中的类型 --></class>
</hibernate-mapping>

测试保存

public class OneToManyTest {// 测试保存@Testpublic void test1() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1创建一个客户Customer c = new Customer();c.setName("张三");// 2.2创建两个订单Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立关系// 2.3.1 订单关联客户o1.setC(c);o2.setC(c);// 2.3.2 客户关联订单c.getOrders().add(o1);c.getOrders().add(o2);session.save(o1);session.save(o2);session.save(c);// 3.事务提交,关闭session.getTransaction().commit();session.close();}
}

上面操作是一种双向关联
问题:我们可不可以只保存订单或只保存客户完成保存操作?

测试单向关联保存

// 测试保存---单向操作(保存订单并自动保存客户)@Testpublic void test2() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1创建一个客户Customer c = new Customer();c.setName("张三");// 2.2创建两个订单Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立关系// 2.3.1 订单关联客户o1.setC(c);o2.setC(c);session.save(o1); // o1是一个持久化对象session.save(o2); // o2是一个持久化对象// 3.事务提交,关闭session.getTransaction().commit();session.close();}

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.nwtxxb.oneToMany.Customer
…………..
这个异常代表提一个持久化对象关联了一个瞬时对象。
我们可以使用级联操作来解决上述的问题.
我们现在要做的是保存订单时保存客户,需要在订单的hbm配置文件中修改

<!-- 多对一 -->
<many-to-one name="c" class="cn.nwtxxb.oneToMany.Customer" column="c_customer_id" cascade="save-update">
</many-to-one>

设置cascade=save-update 那么在保存订单时就可以自动将客户保存。
如果我们要完成保存客户时,保存订单

<!-- 一个客户关联多个订单 -->
<set name="orders" cascade="save-update"><key column="c_customer_id" /><one-to-many class="cn.nwtxxb.oneToMany.Order" />
</set>

双向关联保存

我们在开发中要配置双向关联配置。———可以通过任意一方来操作对方
在操作代码,尽量来要进行单向关联。——可以尽量资源浪费。
在双向关联中,会存在多余的update语句。
我们可以使用inverse属性来设置,双向关联时由哪一方来维护表与表之间的关系。

<!-- 一个客户关联多个订单 -->
<set name="orders" inverse="true" cascade="save-update"><key column="c_customer_id" /><one-to-many class="cn.nwtxxb.oneToMany.Order" />
</set>

Inverse它的值如果为true代表,由对方来维护外键。
Inverse它的值如果为false代表,由本方来维护外键。
关于inverse的取值:
外键在哪一个表中,我们就让哪一方来维护外键。

对象导航

级联删除

我们在删除客户时,也要删除订单,如果没有做级联,那么这个操作是不允许。
为了维护数据完整性

<!-- 一个客户关联多个订单 -->
<set name="orders" inverse="true" cascade="delete"><key column="c_customer_id" /><one-to-many class="cn.nwtxxb.oneToMany.Order" />
</set>

delete-orphan用法

<!-- 一个客户关联多个订单 -->
<set name="orders" inverse="true" cascade="delete-orphan"><key column="c_customer_id" /><one-to-many class="cn.nwtxxb.oneToMany.Order" />
</set>

测试类

public class OneToManyTest {// 级联 cascade= delete-orphan@Testpublic void test6() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 得到客户Customer c = session.get(Customer.class, 2);// 得到客户的订单Order o = session.get(Order.class, 6);c.getOrders().remove(o);// 3.事务提交,关闭session.getTransaction().commit();session.close();}// 测试级联删除@Testpublic void test5() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 操作----删除订单时,不需要删除客户,当我们删除一个客户时,应该将客户对应订单也删除。Customer c = session.get(Customer.class, 1);session.delete(c);// 删除客户?订单是否会删除?// 3.事务提交,关闭session.getTransaction().commit();session.close();}// 测试一对多对象导航@Testpublic void test4() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 操作// 2.1创建一个客户Customer c = new Customer();c.setName("张三");// 2.2创建两个订单Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");Order o3 = new Order();o3.setMoney(3000d);o3.setReceiverInfo("深圳");// 描述关系// o1要关联co1.setC(c);// c要关联o2 o3c.getOrders().add(o2);c.getOrders().add(o3);session.save(o1);// 3.事务提交,关闭session.getTransaction().commit();session.close();}// 测试保存---单向操作(保存客户并自动保存订单)@Testpublic void test3() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1创建一个客户Customer c = new Customer();c.setName("张三");// 2.2创建两个订单Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立关系// 2.3.1 客户与订单关联c.getOrders().add(o1);c.getOrders().add(o2);session.save(c);// 保存客户// 3.事务提交,关闭session.getTransaction().commit();session.close();}// 测试保存---单向操作(保存订单并自动保存客户)@Testpublic void test2() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1创建一个客户Customer c = new Customer();c.setName("张三");// 2.2创建两个订单Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立关系// 2.3.1 订单关联客户o1.setC(c);o2.setC(c);session.save(o1); // o1是一个持久化对象session.save(o2); // o2是一个持久化对象// 3.事务提交,关闭session.getTransaction().commit();session.close();}// 测试保存@Testpublic void test1() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1创建一个客户Customer c = new Customer();c.setName("张三");// 2.2创建两个订单Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立关系// 2.3.1 订单关联客户o1.setC(c);o2.setC(c);// 2.3.2 客户关联订单c.getOrders().add(o1);c.getOrders().add(o2);session.save(o1);session.save(o2);session.save(c);// 3.事务提交,关闭session.getTransaction().commit();session.close();}
}

HibernateUtils工具类

public class HibernateUtils {private static Configuration config;private static SessionFactory sessionFactory;static{config=new Configuration().configure();sessionFactory=config.buildSessionFactory();}public static Session openSession(){return sessionFactory.openSession();}
}

cascade级联操作总结

使用cascade可以完成级联操作
它可常用取值:
none这是一个默认值
save-update,当我们配置它时,底层使用save update或save-update完成操作,级联保存临时对象,如果是游离对象,会执行update.
delete 级联删除
delete-ophan 删除与当前对象解除关系的对象。
all 它包含了save-update delete操作
all-delete-orphan 它包信了delete-orphan与all操作
问题:cascade与inverse有什么区别?
cascade它是完成级联操作
Inverse它只有在双向关联情况下有作用,它来指定由哪一方维护外键。

Hibernate一对多关联映射及cascade级联操作相关推荐

  1. hibernate一对多关联映射

    一对多关联映射 映射原理 一对多关联映射和多对一关联映射的映射原理是一致的,都是在多的一端加入一个外键,指向一的一端.关联关系都是由多端维护,只是在写映射时发生了变化. 多对一和一对多的区别 多对一和 ...

  2. 【SSH系列】Hibernate映射 -- 一对多关联映射

         映射原理        一对多关联映射和多对一关联映射的映射原理是一样一样的,所以说嘛,知识都是相通的,一通百通,为什么说一对多关联映射和多对一关联映射是一样的呢?因为她们都是在多的一端加入 ...

  3. 步步为营Hibernate全攻略(二)剪不断理还乱之:一对多关联映射

    一对多关联映射和多对一关联映射的原理是一致的,都是在多的一端加入一个外键,指向一的一端.但是他们又有所区别,有了多指向一的关系,在加载多的时候可以将一加载上来,而有了一对多的关系,在加载一的时候可以将 ...

  4. 一对多关联映射(单向关联)见项目:me_one_to_many

    1. 模型 一个用户组(group)对应多个用户. 2. 实体类(省略set,get方法) public class User { private int id; private String nam ...

  5. 【Java Web开发指南】Mybatis一对多关联映射

    文章目录 1 嵌套查询 2 嵌套结果 1 嵌套查询 <select id="findUserWithOrders2" parameterType="Integer& ...

  6. Mybatis注解实现一对多关联映射(@Many)

    mybatis注解实现一对多关联映射 @Select("<script> \n" +"\t\tselect a.*,p.punishment_money, p ...

  7. (转)MyBatis框架的学习(五)——一对一关联映射和一对多关联映射

    http://blog.csdn.net/yerenyuan_pku/article/details/71894172 在实际开发中我们不可能只是对单表进行操作,必然要操作多表,本文就来讲解多表操作中 ...

  8. Hibernate②一(多)对多的映射配置与级联操作

    文章目录 1 一对多(部门对员工) 1.0 确定一对多中的关系 1.1 编写实体类 1.2 编写映射配置文件与核心配置文件 2 多对多(学生对教师) 2.0 确定多对多中的关系 2.1 编写实体类 2 ...

  9. 【Hibernate步步为营】--关联映射之多对一

    上篇文章讨论了Hibernate的基本映射,一个实体类对应着一张表,在相应的Hibernate Mapping文件中使用<class>标签映射.并且实体类中的普通属性对应着表字段,使用&l ...

最新文章

  1. 计算机社团部门职责,部门职责
  2. html5 popup,popup.js-jQuery和CSS3可互动的3D弹出窗口插件
  3. 《JavaScript设计模式与开发实践》模式篇(3)—— 代理模式
  4. 1G、3G都失败了,5G也会失败吗?
  5. python测试笔试题1
  6. ps导出gif颜色不对_PS の手绘《超详细的动态表情包新手绘制指南》
  7. 实战开发,使用 Spring Session 与 Spring security 完成网站登录改造!!
  8. spring源码-第七个后置处理器的使用
  9. nginx的安装及配置文件详解
  10. linux u盘 修复工具,怎样Linux下修复U盘驱动器
  11. 皮克定理(格点三角形求面积或求三角形里格点(整点)个数)
  12. Python:50行代码实现下载小说,图片章节可自动识别转文字保存...
  13. yolov3.weight
  14. 趣图:五彩斑斓的黑,找到了
  15. 让我们看看往年的1024传智播客怎么安排的
  16. Unity SteamVR锁定头盔位置旋转
  17. xls和xlsx的区别
  18. 联想 Thinkpad T440p驱动程序下载列表(转发文章)
  19. 【数学有什么用处?看完后恍然大悟!】
  20. 黑客入侵 应用程序无法启动_被黑客入侵如何启动我的网络安全职业

热门文章

  1. 【深度学习】一分钟速学 | NMS, IOU 与 SoftMax
  2. 快速掌握TensorFlow中张量运算的广播机制
  3. 吴恩达老师的机器学习和深度学习课程笔记打印版
  4. 技术干货 | 基于 Qt Quick Plugin 快速构建桌面端跨平台组件
  5. 从入门到进阶|如何基于WebRTC搭建一个视频会议
  6. 网易云信三周年:我们只做第一
  7. AES加密算法动画演示
  8. 15.Node.js REPL(交互式解释器)
  9. Eclipse与MyEclipse增强代码提示
  10. 《sed的流艺术之四》-linux命令五分钟系列之二十四