博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(八)Hibernate的一对多关联关系
阅读量:5975 次
发布时间:2019-06-20

本文共 10467 字,大约阅读时间需要 34 分钟。

一、概述

例如,以客户(Customer)和订单(Order)为例,一个客户能有多个订单,一个订单只能有一个客户。 从Customer到Order是一对多关联,在java类中的面向对象设计应该一个Customer对象包含多个Order对象,因此应该定义一个集合,来包含所有的Order对象。  从Order到Customer是多对一关联,在java类中设计每个Order对象需要关联一个Customer对象,因此Order类中应该定义一个Cutomer类型的属性,来引用关联的customer对象。但是在关系数据库中,只存在主外键参照关系来表达两者的关联。

  

 

二、实例

(1)先创建两个实体类 Customer和Order

public class Customer {                    private Integer id;                    private String name;                    private Set 
orders=new HashSet
(); 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 Set getOrders() { return orders; } public void setOrders(Set orders) { this.orders = orders; } } public class Order { private Integer id; private String name; private Customer customer; 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 Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } }

 (2)实体类写好了,使用Hibernate映射文件来映射关系 

创建Customer.hbm.xml:

Hibernate根据映射文件获得以下信息 -
元素表明Customer类中的orders属性为java.util.Set集合 -
元素表明orders集合中存放的是一组order对象 -
元素表明orders表通过外键cid关联customer表

  

创建Order.hbm.xml

 

 (3)在hibernate.cfg.xml中配置映射文件

 (4)测试

//添加方法                      @Test                    public void test() {                        //读取配置文件                        Configuration conf=new Configuration().configure();                        //根据配置创建factory                        SessionFactory sessionfactory=conf.buildSessionFactory();                        session = sessionfactory.openSession();                          Transaction ts=session.beginTransaction();                          //创建Customer                        Customer c=new Customer();                        c.setName("张三");                         //创建订单                        Order o1=new Order();                        o1.setName("矿泉水");                        Order o2=new Order();                        o2.setName("方便面");                         //双向关联                        c.getOrders().add(o1);                        c.getOrders().add(o2);                        o1.setCustomer(c);                        o2.setCustomer(c);                        //保存                        session.save(c);                        session.save(o1);                        session.save(o2);                        ts.commit();                        session.close();                        sessionfactory.close();                    }                    然后执行,控制台会打印如下语句                            Hibernate:                                 insert                                 into                                    customer                                    (name)                                 values                                    (?)                            Hibernate:                                 insert                                 into                                    orders                                    (name, cid)                                 values                                    (?, ?)                            Hibernate:                                 insert                                 into                                    orders                                    (name, cid)                                 values                                    (?, ?)                            Hibernate:                                 update                                    orders                                 set                                    cid=?                                 where                                    id=?                            Hibernate:                                 update                                    orders                                 set                                    cid=?                                 where                                    id=?

  我们来执行删除操作,直接删除Customer,但由于还有Order关联着Customer 会执行成功么?

@Test                            public void test() {                                //读取配置文件                                Configuration conf=new Configuration().configure();                                //根据配置创建factory                                SessionFactory sessionfactory=conf.buildSessionFactory();                                session = sessionfactory.openSession();                                  Transaction ts=session.beginTransaction();                                 Customer c=session.get(Customer.class, 2);                                  //删除Customer                                session.delete(c);                                ts.commit();                                session.close();                                sessionfactory.close();                            }                        执行,打印如下语句                            Hibernate:                                 select                                    customer0_.id as id1_0_0_,                                    customer0_.name as name2_0_0_                                 from                                    customer customer0_                                 where                                    customer0_.id=?                            Hibernate:                                 update                                    orders                                 set                                    cid=null                                 where                                    cid=?                            Hibernate:                                 delete                                 from                                    customer                                 where                                    id=?         我们会发现Hibernate会自动将Order中的cid设置为null,然后执行删除操作        我们发现Hibernate还是挺智能的,但这是由inverse属性操控的。

  

三、< set >元素的inverse属性

 

inverse所描述的是对象之间关联关系的维护方式。 inverse属性指定由哪方来维护关联关系。inverse默认为false,即关联关系由自己控制,若为true,则反转,关联关系由对方控制.Inverse属性的作用是:是否将对集合对象的修改反映到数据库中。 在映射一对多的双向关联关系中,应该在"一"方把inverse属性设为true,由对方来维护主键关联关系.所以上述例子中,inverse默认是false.即Customer维护关联关系,所以Customer会执行两条更新语句来更新Order的cid.但是我们Order在插入的时候已经插入cid,所以这样会影响性能,我们只需要将Customer的
元素的inverse属性改为true即可。 我们的删除案例中也是,Customer执行删除时,会先去把Order的主键约束解除,然后删除。我们只需要将Customer的inverse设置为true,然后由对方维护关联关系,我们再进行删除时,就会出现异常,因为有主键约束,我们Customer不再维护关联关系。

 

四、级联操纵

在实际应用中,对象和对象之间是相互关联的。例如我们的一对多关联关系。 

在关系-对象映射文件中,用于映射持久化类之间关联关系的元素,如 < set>,< many-to-one>,< one-to-many>,都有一个cascade属性,用来指定如何操纵与当前对象关联的其他对象。

我们先看下面的例子,我们创建一个Customer,再创建两个Order,然后关联    我们只保存Customer,会抛出org.hibernate.TransientObjectException异常,这是为什么呢?    这是因为我们的Customer的inverse为false,关联关系由Customer维护。我们保存Customer时,    会维护Customer中orders中的所有Order的主键,但是Order是临时对象,并没有转变为持久状态,这时候就会抛出异常。            @Test            public void test() {                //读取配置文件                Configuration conf=new Configuration().configure();                //根据配置创建factory                SessionFactory sessionfactory=conf.buildSessionFactory();                session = sessionfactory.openSession();                  Transaction ts=session.beginTransaction();                 Customer c=new Customer();                 c.setName("jack");                 Order o1=new Order();                 o1.setName("苹果");                 Order o2=new Order();                 o2.setName("香蕉");                 c.getOrders().add(o1);                 c.getOrders().add(o2);                 o1.setCustomer(c);                 o2.setCustomer(c);                 session.save(c);                ts.commit();                session.close();                sessionfactory.close();            }

 当Hibernate持久化一个临时对象时,并不会自动持久化所关联的其他临时对象,所以会抛出异常。 

如果我们希望Hibernate持久化对象时自动持久化所关联的其他对象,那么就需要指定cascade属性 

 (1)级联保存和更新

当我们持久化对象时自动持久化所关联的其他对象。     把cascade属性设置为save-update ,这时候我们再执行上面的代码就会自动帮我们保存Customer关联的Order对象。    当cascade属性为save-update时,表明保存或更新当前对象时,会级联保存或更新与它关联的对象。

 (2)级联删除

如果我们的cascade属性为delete时,我们删除当前对象,会自动删除与之关联的对象。    慎用这个delete属性。    例如:我们的Order配置了这个属性,Customer也配置了这个属性,我们删除订单时,因为是级联删除    所以会查找Customer,删除Customer,但Customer也配置了级联删除,所以会查找所有关联的订单,最后会删除该客户的所有订单和该客户。

 (3)孤儿删除

如果我们的对象和关联的对象解除关系后,希望自动删除不再关联的对象。    需要将cascade设置为delete-orphan.    例如 ,我们设置cascade="delete-orphan"                     Transaction ts=session.beginTransaction();                     Customer c=session.get(Customer.class, 7);                     Order order=(Order) c.getOrders().iterator().next();                     c.getOrders().remove(order);                     order.setCustomer(null);                     ts.commit();     我们解除Customer和Order的关系,Hibernate就会自动删除Order。      当cascade的值为all时,是save-update和delete的整合。    当cascade的值为all-dalete-orphan时,是all和delete-orphan的整合。

  

 

 

 

 

转载于:https://www.cnblogs.com/yuexiaoyun/p/9452363.html

你可能感兴趣的文章
基本安装lnmp环境
查看>>
yum源资料汇总
查看>>
7、MTC与MTV,http请求介绍
查看>>
logstash消费阿里云kafka消息
查看>>
unix 环境高级编程
查看>>
MAXIMO 快速查找实现
查看>>
Oracle——条件控制语句
查看>>
第一次作业-准备篇
查看>>
day-6 and day-7:面向对象
查看>>
CSU Double Shortest Paths 湖南省第十届省赛
查看>>
webgl像机世界
查看>>
php正则怎么使用(最全最细致)
查看>>
javascript数学运算符
查看>>
LC.155. Min Stack(非优化,两个stack 同步 + -)
查看>>
交互设计[3]--点石成金
查看>>
SCCM TP4部署Office2013
查看>>
redis主从配置<转>
查看>>
bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理...
查看>>
利用console控制台调试php代码
查看>>
递归算法,如何把list中父子类对象递归成树
查看>>