zoukankan      html  css  js  c++  java
  • Hibernate总结(二)

    在上一篇Hibernate总结(一)简单总结了一级缓存,快照,增删改查的简单使用,这一篇总结两张表的级联操作

    级联涉及到三种情况,many-many,1-many,many-1。

    • 首先是1-many,many-1情况,所以先设置一个情景:客户与订单的关系
    //因为太占版面缘故,没有列出get()/set()方法
    public class Customer {
        private Integer id;
        private String name;
        private Set<Order> orders = new HashSet<Order>();//1对多
    }
    public class Order {
        private Integer id;
        private String name;
        private Customer customer;//多对1
    }

    接下来是hibernate.cfg.xml与两个实体类的配置文件Order.hbm.xml与Customer.hbm.xml,第一个不多说,主要是映射文件的配置

    //Customer.hbm.xml
    <hibernate-mapping package="king.domain">
        <class name="Customer" table="t_customer">
            <id name="id" column="id">
                <generator class="native"></generator>
            </id>
            <property name="name" column="name"></property>
            <!-- 一对多关系 -->
            <!-- 
           inverse:true 不维护关系,交给拥有外键一方维护
           cascade:save-update(级联保存与级联更新),当然还有其它选项,delete(级联删除),all(级联保存,更新,删除),none(默认没有级联)
       --> <set name="orders" inverse="true" cascade="save-update"> <key column="cid"></key> <!-- 在Order表中的外键的名字--> <one-to-many class="Order"/> </set> </class> </hibernate-mapping> //Order.hbm.xml <hibernate-mapping package="king.domain"> <class name="Order" table="t_order"> <id name="id" column="id"> <generator class="native"></generator> </id> <property name="name" column="name"></property> <!-- 多对一关系 --> <!-- 含有外键一方维护关系 --> <many-to-one name="customer" column="cid" class="Customer"></many-to-one> </class> </hibernate-mapping>

    一切准备就绪,开始级联的代码:

    因为代码中大量使用了得到连接,关闭连接操作,所以我使用了模板设计模式,在我的文章《Hibernate-模板模式有讲解

        /**
         * 级联保存:
         * 1.inverse="true",维护关系,最好只有一方维护,而且是拥有外键一方维护
         * 2.cascade="save-update",级联保存与级联更新
         */
        @Test
        public void test0() {
            new SessionTemplate(){
                @Override
                public void fun(Session s) {
                    Customer c=new Customer();
                    c.setName("King");
                    Order o1=new Order();
                    o1.setName("炒面");
                    Order o2=new Order();
                    o2.setName("肉");
                    
                    o1.setCustomer(c);//由拥有外键一方维护关系
                    o2.setCustomer(c);
                    
                    s.save(c);
                    s.save(o1);
                    s.save(o2);//这样框架只执行了3条SQL语句
                }
            }.execute();
        }
        /**
         * 级联删除:
         * 1.inverse="false"为默认处理方式:把客户的订单的外键修改为null,然后再删除客户
         * 2.inverse="true"若客户不处理,会出错
         */
        @Test
        public void test1() {
            new SessionTemplate(){
                @Override
                public void fun(Session s) {
             //这是没有使用级联删除的情况,这时cascade为save-update Customer c
    =(Customer) s.get(Customer.class, 3); for(Order o:c.getOrders()){ s.delete(o); } s.delete(c);//此时,inverse="true",所以前面删除了所有客户的订单才能删除客户

             //更改配置文件,cascade为delete,这时就是级联删除
                    Customer c=(Customer) s.get(Customer.class, 3);
                    s.delete(c);//这时不需要手动删除订单了
                }
            }.execute();
        }
        /**
         * 级联更新
       * cascade为save-update 
    */ @Test public void test2() { new SessionTemplate(){ @Override public void fun(Session s) { Customer c=(Customer) s.get(Customer.class, 2); for(Order o:c.getOrders()){ o.setName("羊杂汤");//持久态,不需要更新 } } }.execute(); }

    查询涉及到了加载策略,所以很复杂,所以将在写在下一篇中。

    • 接下来说many-many的情况,还是先设置一个情景:学生与课程的关系
    public class Student {
        private Integer id;
        private String name;
        private Set<Course> courses=new HashSet<>();//多对多
    }
    public class Course {
        private Integer id;
        private String name;
        private Set<Student> students=new HashSet<>();//多对多
    }

    接下来是两个实体类与数据库表的映射文件:

    //Student.hbm.xml
    <hibernate-mapping package="king.domain">
        <class name="Student" table="t_student">
            <id name="id" column="id">
                <generator class="native"></generator>
            </id>
            <property name="name" column="name"></property>
            <!-- 多对多关系,在多对多中,需要双方都设置存储关系的表名 -->
            <set name="courses" cascade="save-update" table="t_selectcourse">
                <key column="sid"></key>
                <many-to-many class="Course" column="cid"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>
    //Course.hbm.xml
    <hibernate-mapping package="king.domain">
        <class name="Course" table="t_course">
            <id name="id" column="id">
                <generator class="native"></generator>
            </id>
            <property name="name" column="name"></property>
            <!-- 多对多关系 -->
            <!-- 维护权反转给对方 -->
            <set name="students" inverse="true" table="t_selectcourse">
                <key column="cid"></key>
                <many-to-many class="Student" column="sid"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>

    一切准备继续,开始代码工作:

        /**
         * 多对多
         * 级联保存:
       * 本来想也写上级联删除与级联更新,但是发现写的代码和我想要实现的结果不同,故没有贴出代码,额...我的意思就是我也不会...挺尴尬...
    */ @Test public void test0() { new SessionTemplate(){ @Override public void fun(Session s) { Student s1=new Student(); s1.setName("King"); Course c1=new Course(); c1.setName("数学"); Course c2=new Course(); c2.setName("英语"); s1.getCourses().add(c1);//由学生维护关系 s1.getCourses().add(c2);//由学生维护关系 s.save(s1); } }.execute(); }

    增删改查,现在就差“查”没有写出,我将在下一篇总结中写出Hibernate的关于查询的加载策略。

  • 相关阅读:
    Git衍合和合并区别
    Git开发流程
    AJAX用户注册演示程序
    PHP常用MySql操作
    轻描淡写
    浅谈web后门隐藏与检测思路
    PHP代码审计和漏洞挖掘的一点思考
    Android Split的用法
    Android 动态显示时间
    Java 获取字符长度
  • 原文地址:https://www.cnblogs.com/kingofkai/p/6023415.html
Copyright © 2011-2022 走看看