hibernate 一对多_Hibernate配置文件详解-2

7fe0b740dccd06a280003de20a7348da.png
前言:

上一篇文章我们学习了Hibernate的配置详解,主要包括两个配置文件,

hibernate.cfg.xml和hbm.xml。

今天继续来学习hbm.xml中两个重要的配置:

inverse和cascade。

1.inverse

在具体业务场景中,Customer和Orders是一对多关系,一个Customer对应多个Orders,实体类中用一个set集合作为属性来表示对应的Orders。

public class Customer { private int id; private String name; private Set orders; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set getOrders() { return orders; } public void setOrders(Set orders) { this.orders = orders; }}

Customer.hbm.xml文件中用set标签来配置映射关系。

<?xml version="1.0" encoding="UTF-8"?>

同理在Orders实体类中用一个Customer类型的属性来表示对应的Customer对象。

public class Orders { private int id; private String name; private Customer customer; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; }}

Orders.hbm.xml中,用many-to-one标签来配置映射关系。

<?xml version="1.0" encoding="UTF-8"?>

从配置文件中可以看出,Customer和Orders是双向维护关系,即Customer在维护一对多关系,同时Orders也在维护一对多关系,在实际开发代码过程中,就可能会出现重复维护的情况。

创建一个Customer对象,创建两个Orders对象,并建立关联关系,Orders对象来维护一对多关系,代码如下。

 //创建customer对象 Customer customer = new Customer(); customer.setName("张三"); //创建orders1对象 Orders orders1 = new Orders(); orders1.setName("订单1"); //将customer赋给orders1 orders1.setCustomer(customer); //创建orders2对象 Orders orders2 = new Orders(); orders2.setName("订单1"); //将customer赋给orders2 orders2.setCustomer(customer); //保存 session.save(customer); session.save(orders1); session.save(orders2); //提交事务 session.beginTransaction().commit(); //关闭session session.close();

执行代码,打印3条SQL语句,向customer表添加1条记录,向orders表添加2条记录,并且将customer的id值赋给cid字段,建立主外键约束关系。这段代码没有什么问题。

aa2509ba8190a6d2aa2d2c8c27bb7a98.png

此时修改Java代码,让Customer对象也来维护一对多关系。

 //创建customer对象 Customer customer = new Customer(); customer.setName("张三"); //创建orders1对象 Orders orders1 = new Orders(); orders1.setName("订单1"); //将customer赋给orders1 orders1.setCustomer(customer); //创建orders2对象 Orders orders2 = new Orders(); orders2.setName("订单1"); //将customer赋给orders2 orders2.setCustomer(customer); //创建集合,将orders1,orders2加入集合 Set ordersSet = new HashSet(); ordersSet.add(orders1); ordersSet.add(orders2); //将Orders集合赋给customer customer.setOrders(ordersSet); //保存 session.save(customer); session.save(orders1); session.save(orders2); //提交事务 session.beginTransaction().commit(); //关闭session session.close();

再次执行代码,打印5条SQL,向customer表添加1条记录,向orders表添加2条记录,并且将customer的id值赋给cid字段,建立主外键约束关系。

同时多了2条修改操作,再一次将customer的id值赋给cid字段,这2条SQL语句是在重复设置已经建立的主外键约束关系。

为什么会出现这种情况?

因为当前Customer和Orders对象都在维护关系,所以会重复建立两次主外键约束。

如何避免这种情况的出现呢?

第一种方式:在Java代码中去掉一方维护关系的代码。

第二种方式:通过设置hbm.xml文件来完成。

通常我们让多的一方来维护关系,即让Orders来维护,所以就需要让Customer放弃维护,在Customer.hbm.xml中设置set标签的inverse属性。

inverse属性是用来设置是否将维护权交给对方,默认为false,即不交出维护权,双方都在维护关系。

现在将invers设置为true,表示当前Customer已经放弃了维护权。

再次运行代码。

b92231fbe1933deb0277905c20123621.png
aa2509ba8190a6d2aa2d2c8c27bb7a98.png

看到控制台打印3条SQL,即建立了一次主外键约束关系,并且是由Orders来维护的。

2.cascade:用来设置级联操作。

我们知道在删除一条主表数据时,一定要先清除被它约束的从表记录,

即在删除Customer对象时,必须先删除该对象对应的Orders对象,否则直接报错。

ad329369fef92d784858955b60ae6d04.png
3b39b49d4583e810c0ce2f6e2e5b57ef.png

错误原因是因为被删除记录的主键正在约束orders表中的外键,必须先解除约束关系,才可删除。

如何解决?

第一种方式:修改Java代码,迭代Customer对象包含的所有Orders对象,将这些Orders对象全部删除,再删除Customer对象。

 Customer customer = (Customer) session.get(Customer.class, 10); //迭代orders集合 Iterator iter = customer.getOrders().iterator(); while(iter.hasNext()){ Orders orders = (Orders) iter.next(); //删除orders对象 session.delete(orders); } session.delete(customer); session.beginTransaction().commit(); session.close();

第二种方式:不需要修改Java代码,在hbm.xml中设置级联删除属性即可,设置cascade="delete"。

cascad:有4个值可以选择。

1.all: 所有情况下均进行关联操作。

2.none:所有情况下均不进行关联操作。这是默认值。

3.save-update:在执行save/update/saveOrUpdate时进行关联操作。

4.delete:在执行delete时进行关联操作。

执行代码。

a1866a15b3ea352e35101b82914dd271.png

会看到控制台会打印3条delete语句,前2条是删除Customer对象关联的2个Orders对象,第3条是删除Customer对象本身。

采用这种方式,我们不需要在逻辑代码中手动删除级联对象,Hibernate框架会自动帮我们删除这些对象。

关注微信公众号「Java大联盟」,关注即可获取海量学习干货,同时还有不定期送书,键盘,鼠标等粉丝福利。

61ad28d0356c0dfb483b333a4ca4f002.png

赶快来关注一波,海量资源拿到手软。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值