博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习hibernate(五) -- hibernate映射关系
阅读量:6592 次
发布时间:2019-06-24

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

hot3.png

组合关系

    在开发时,有一种情况,有一张数据表的数据来自于多个对象。比如,一个computer(电脑)表,其中有电脑的基本信息、CPU信息、显卡信息、主板信息和内存信息等等,对应的实体对象则是电脑对象、CPU对象、显卡对象和内存对象。这种情况下可以使用组合关系映射。

    以电脑与CPU为例,Computer类中包含了一个Cpu类,在*.hbm.xml文件中,使用component来进行组合关系映射。

    看一下这两个实体类的代码和映射文件:

package cn.net.bysoft.model;public class Computer {//getter and setter    private int id;    private String name;    private Cpu cpu;}
package cn.net.bysoft.model;public class Cpu {    //getter and setter    private String name;}
    
        
            
            
                
        
        
            
            

    生成的数据表并测试save方法:

@Test    public void testComponent() throws IOException {        //    save一个组合关系对象。        Computer computer = new Computer();        computer.setName("pc");        Cpu cpu = new Cpu();        cpu.setName("Inter");        computer.setCpu(cpu);        session.save(computer);    }

181926_IKI2_2450666.png

一对多与多对一

    一对多与多对一关联,一般用于一个对象包含另一个对象的集合,被包含的对象中存在包含对象的实体,比如一个customer可以有多比订单(order)。在数据表中,order表有customer表的外键。

    在*.hbm中,一的一端使用set标签设置多的一端的集合,在set中加入key与one-to-many。

    多的一端使用<one-to-may>属性配置一对多。

    看一下实体类代码和配置文件:

package cn.net.bysoft.model1;import java.util.HashSet;import java.util.Set;public class Customer {    getter/setter属性        private int Id;    private String name;    //    一对用户可以有多个订单。    private Set
 orders = new HashSet
();}
package cn.net.bysoft.model1;public class Order {    getter/setter属性        private int id;    private String name;    //    每个订单都属于一个用户。    private Customer customer;}
    
        
            
            
                
        
        
            
            
            
    
        
            
            
                
        
        
            

    新增和删除的时候有一些需要注意的地方,看一段save代码:

    @Test    public void testOneToManySave() {        Customer customer = new Customer();        customer.setName("Kobe");        Order order1 = new Order();        order1.setName("buy book");        Order order2 = new Order();        order2.setName("buy ball");        customer.getOrders().add(order1);        customer.getOrders().add(order2);        order1.setCustomer(customer);        order2.setCustomer(customer);        session.save(customer);        session.save(order1);        session.save(order2);        /**         * output: Hibernate:          * insert into CUSTOMERS (NAME) values (?)          * insert into ORDERS (NAME, CUSTOMER_ID) values (?, ?)          * insert into ORDERS (NAME, CUSTOMER_ID) values (?, ?)         * */    }

    先save一的一端,在save多的一端,会打印三条sql语句,是正常的。如果先保存多的一端在保存一的一端,会输出七条sql语句,其中有4条是update语句,因为先保存多的一端,此时并没有一的一端的主键,等到保存好一的一端后,在回头由两端都进行update。

        session.save(order1);        session.save(order2);        session.save(customer);        /**         * output:          * Hibernate: insert into ORDERS (NAME, CUSTOMER_ID) values (?,?)          * Hibernate: insert into ORDERS (NAME, CUSTOMER_ID) values (?, ?)         * Hibernate: insert into CUSTOMERS (NAME) values (?)          * Hibernate: update ORDERS set NAME=?, CUSTOMER_ID=? where ID=?          * Hibernate: update ORDERS set NAME=?, CUSTOMER_ID=? where ID=?          * Hibernate: update ORDERS set CUSTOMER_ID=? where ID=?          * Hibernate: update ORDERS set CUSTOMER_ID=? where ID=?         * */

    正常来说,不需要两端都进行update维护,要解决该问题需要在一端加入inverse属性,建议由多的一端去控制,所以在Customer.hbm.xml中的set节点中加入:

    在进行保存时,update语句减少了,只由多的一端维护关系:

175954_WoP5_2450666.png

    再来说说delete。删除时在不设置级联的情况下,不能删除一的一端,因为这一端的主键被关键关联着:

    @Test    public void testOneToManyDelete() {        Customer customer = (Customer) session.get(Customer.class, 1);        session.delete(customer);        /**         * output:          * INFO: HHH000010: On release of batch it still contained JDBC statements         * */    }

    使用级联关系的属性是cascade,该属性有三个值,分别是:

  • delete:删除一的一端,会连带着删除多的一端;

  • delete-orphan:一的一端使用多的一端的集合的clear属性可以删除多的一端;

  • save-update:值保存一的一端,多的一端会自动保存;

    在设置好级联关系后,可直接删除一的一端:

    在项目中建议使用手动控制关联关系。

一对一

    有两种情况均为一对一关联关系,一个部门有一个部门经理。可以使用某一个字段做外键,也可以使用主键做外键。先来看看主外键情况做一对一。

    在Manager对象的配置文件中加入<one-to-one>节点,而Dept对象中加入<many-to-one>节点,对该节点加入unique属性进行唯一约束,下面是实体类与配置文件内容:

package cn.net.bysoft.model1;public class Dept {    //getter/setter    private int id;    private String name;    private Manager manager;}
package cn.net.bysoft.model1;public class Manager {    //getter/setter        private int id;    private String name;    private Dept dept;}
    
        
            
            
                
        
        
    
    
        
            
            
                
        
        
    

    接下来是主键与主键做一对一关系,实体类无需改变,只需要修改dept的配置文件,将id节点的class修改成foreign模式,将many-to-one修改成one-to-one,添加constrained属性等于true,具体如下:

    
        
            
            
                
manager                            
        
            

    增删改查方法的调用与一对多多对一一样。

多对多

    用数据表描述多对多,需要有三张表,A表,B表,A-R-B表。

    用对象描述多对多,A对象中有B对象的集合,B对象中也有A对象的集合。

    举个例子,现在有订单类与商品类,一个订单中可以有多个商品,而一个商品也可以属于多个订单。看一下实体类的代码:

package cn.net.bysoft.model1;import java.util.HashSet;import java.util.Set;public class Orders {    //getter and setter    private int id;    private String name;    private Set
 products = new HashSet
();}
package cn.net.bysoft.model1;import java.util.HashSet;import java.util.Set;public class Products {    //getter and setter    private int id;    private String name;    private Set
 orders = new HashSet
();}

    两个对象的配置文件也很像,每个配置文件中都有set节点,但是在多对多中,必须有一个set的inverse=true,具体如下:

235947_cUT3_2450666.png

235948_3L4k_2450666.png

    使用方式与一对多多对一相同。

转载于:https://my.oschina.net/u/2450666/blog/653932

你可能感兴趣的文章
Extjs - Panel组件
查看>>
收集参数及反转过程
查看>>
PPTP××× 数据分流
查看>>
我的友情链接
查看>>
mongodb 索引
查看>>
dhcp服务的讲解和在Linux环境下的搭建
查看>>
PHP fopen和fwrite函数实现创建html页面
查看>>
Citrix 宣布 XenServer 全面开源
查看>>
我的友情链接
查看>>
oracle 如果为空则输出0
查看>>
Mysql聚合函数count(*) 的性能分析
查看>>
[Cordova-IOS]JavaScript与Swift交互
查看>>
Spfa(最短路求解)
查看>>
用一个view来自定义tabbarController,可以实现隐藏
查看>>
使用linux-c编程实现简单的ls命令
查看>>
Q:按F12进行网络安装系统时,一直无法进入,提示加载失败?
查看>>
我的友情链接
查看>>
基于SSH框架、Oracle数据库、easyui的分页显示
查看>>
解决AutoCAD acmgd.dll ARX命令中发现异常
查看>>
[转]passport.js学习笔记
查看>>