Hibernate多表设计及映射

1.多表设计
在开发中,前期进行需求分析,需求分析提供E–R图,根据ER图编写表结构。
表之间关系存在3种:一对多、多对多、一对一。(回顾)
这里写图片描述
一对多:1表(主表)必须主键 和 多表(从表)必须外键,主表的主键 与 从表外键 形成主外键关系

多对多:提供中间表(从表),提供2个字段(外键)分别对应两个主表。

一对一:???

面单对象描述 对象与对象 之间关系?【掌握】
一对多:客户和订单

private class Customer{
        //一对多:一个客户 拥有 多个订单
        private Set<Order> orderSet;
        }
        private class Order{
        //多对一:多个订单 属于 一个客户
        private Customer customer;
    }

多对多:Student学生 和 Course课程

private class Student{
        //多对多:多个学生(当前)学习 【不同课程】
        private Set<Course> courseSet ...;
        }
        private class Course{
        //多对多:多个课程 可以被 【不同学生】学习
        private Set<Student> student = ...;
    }

一对一:公司company 和 地址address

    private class Company{
        private Address address;
    }
    private class Address{
        private Company company;
    }

2.关联关系映射

2.1一对多实现【掌握】

2.1.1实现类

public class Customer {

    private Integer cid;
    private String cname;

    //一对多:一个客户(当前客户) 拥有 【多个订单】
    // * 需要容器存放多个值,一般建议Set (不重复、无序)
    // * 参考集合:List、Map、Array等 
    // ** 建议实例化--使用方便
    private Set<Order> orderSet = new HashSet<Order>();
}
public class Order {
    private Integer xid;
    private String price;

    //多对一:多个订单属于【一个客户】
    private Customer customer;
}

2.1.2配置文件
Customer.hbm.xml

<class name="com.itheima.b_onetomany.Customer" table="t_customer">
        <id name="cid">
            <generator class="native"></generator>
        </id>
        <property name="cname"></property>

        <!-- 一对多:一个客户(当前客户) 拥有 【多个订单】
            1 确定器  set <set>
            2 name确定对象属性名
            3 确定从表外键的名称
            4 确定关系,及另一个对象的类型
            注意:
                在hibernate中可以只进行单向配置
                每一个配置项都可以完整的描述彼此关系。
                一般情况采用双向配置,双方都可以完成描述表与表之间关系。
         -->
        <!-- 一对多:一个客户(当前客户) 拥有 【多个订单】 -->
        <set name="orderSet" cascade="delete-orphan">
            <key column="customer_id"></key>
            <one-to-many class="com.itheima.b_onetomany.Order"/>
        </set>
    </class>

Order.hbm.xml

<class name="com.itheima.b_onetomany.Order" table="t_order">
        <id name="xid">
            <generator class="native"></generator>
        </id>
        <property name="price"></property>

        <!-- 多对一:多个订单属于【一个客户】 
            * name 确定属性名称
            * class 确定自定义类型
            * column 确定从表的外键名称
        -->
        <many-to-one name="customer" class="com.itheima.b_onetomany.Customer" column="customer_id"></many-to-one>
    </class>

这里写图片描述
2.2一对多操作

2.2.1保存客户

@Test
    public void demo01(){
        // 1 创建客户,并保存客户--成功
        Session session = factory.openSession();
        session.beginTransaction();

        Customer customer = new Customer();
        customer.setCname("田志成");
        session.save(customer);
        session.getTransaction().commit();
        session.close();
    }

2.2.2保存订单

@Test
    public void demo02(){
        // 2 创建订单,保存订单--成功,外键为null
        Session session = factory.openSession();
        session.beginTransaction();

        Order order = new Order();
        order.setPrice("998");

        session.save(order);
        session.getTransaction().commit();
        session.close();
    }

2.2.3客户关联订单,只保存客户

@Test
    public void demo03(){
        // 3 创建客户和订单,客户关联订单,保存客户?
        Session session = factory.openSession();
        session.beginTransaction();

        //1 客户和订单
        Customer customer = new Customer();
        customer.setCname("成成");

        Order order = new Order();
        order.setPrice("998");

        //2 客户关联订单
        customer.getOrderSet().add(order);

        //3 保存客户
        session.save(customer);

        session.getTransaction().commit();
        session.close();
    }

这里写图片描述
2.2.4双向关联,使用inverse
这里写图片描述

@Test
    public void demo04(){
        // 4  创建客户和订单,客户关联订单,订单也关联客户,保存客户和订单? 
        // * 开发中优化程序 , n + 1 问题?
        // ** 解决方案1:客户不关联订单 ,不建议
        // ** 解决方案2:客户放弃对订单表外键值的维护。
        // **** Customer.hbm.xml <set name="orderSet" inverse="true">
        // ** inverse 将维护外键值的权利交予对象。相当于自己放弃。(反转)
        Session session = factory.openSession();
        session.beginTransaction();

        //1 客户和订单
        Customer customer = new Customer(); 
        customer.setCname("成成");

        Order order = new Order();
        order.setPrice("998");

        //2 客户关联订单
        customer.getOrderSet().add(order);
        //3 订单也关联客户
        order.setCustomer(customer);

        //4 保存客户
        // * 1 save(order) -- insert  --> 1,998 null
        // * 2 订单管理客户,此时null --预留update --> 更新所有(正常设置)
        // * 3 save(customer) -- insert --> 1,成成
        // * 4 客户关联订单  --> 预留update --> 更新订单外键 (维护外键)
        // * 5 提交commit --> 执行2 和 4 
        session.save(order);
        session.save(customer); 

        session.getTransaction().commit();
        session.close();
    }

在一对多开发中,一方一般都放弃对外键值的维护。及

<set inverse="truen

2.3级联操作(读、理解)

2.3.1save-update 级联保存或更新
这里写图片描述

@Test
    public void demo032(){
        // 32 创建客户和订单,客户关联订单,保存客户? --抛异常
        // ** 解决方案2:级联操作--级联保存或更新
        // ** Customer.hbm.xml <set cascade="save-update">
        // ** 在保存客户的同时,一并保存订单
        Session session = factory.openSession();
        session.beginTransaction();

        //1 客户和订单
        Customer customer = new Customer();     //瞬时态
        customer.setCname("成成");

        Order order = new Order();              //瞬时态
        order.setPrice("998");

        //2 客户关联订单
        customer.getOrderSet().add(order);

        //3 保存客户
        session.save(customer);                 //持久态
        // 关联操作都是持久态的,此时 持久态Customer 引用 一个 瞬时态的Order 抛异常

        session.getTransaction().commit();
        session.close();
    }

2.3.2delete 级联删除
这里写图片描述

@Test
    public void demo05(){
        // 5 查询客户,并删除(持久态)
        // 默认:当删除客户,默认将订单外键设置成null。
        // 级联删除:删除客户时,并将客户的订单删除。
        // ** Customer.hbm.xml <set name="orderSet" cascade="delete">
        Session session = factory.openSession();
        session.beginTransaction();
    //查询到确定某个用户id为10        
        Customer customer = (Customer) session.get(Customer.class, 10);

        session.delete(customer);
        session.getTransaction().commit();
        session.close();
    }

2.3.3孤儿删除
一对多关系,存在父子关系。1表(主表)可以成为父表,多表(从表)也可以子表。
这里写图片描述
这里写图片描述
总结:
主表不能删除,从表已经引用(关联)的数据
从表不能添加,主表不存在的数据。
这里写图片描述

@Test
    public void demo06(){
        // 6 查询客户,并查询订单,解除客户和订单订单的关系
        // * 默认:客户和订单解除关系后,外键被设置成null,此时订单就是孤儿。客户和订单都存在。
        // * 孤儿删除(孤子删除),当订单称为孤儿,一并删除。客户仍存在。
        Session session = factory.openSession();
        session.beginTransaction();

        //1 查询客户
        Customer customer = (Customer) session.get(Customer.class, 9);

        //2查询订单
        Order order = (Order) session.get(Order.class, 8);

        //3 解除关系
        customer.getOrderSet().remove(order);

        session.getTransaction().commit();
        session.close();
    }

2.3.4总结
save-update:A保存,同时保存B
delete:删除A,同时删除B,AB都不存在
delete-orphan:孤儿删除,解除关系,同时将B删除,A存在的。
如果需要配置多项,使用逗号分隔。

all : save-update 和 delete 整合
all-delete-orphan : 三个整合

over~~~

展开阅读全文

没有更多推荐了,返回首页