zoukankan      html  css  js  c++  java
  • Hibernate(10)_双向n对1(双向1对n)

    1.双向 1-n 与 双向 n-1 是完全相同的两种情形,这里使用双向多对一来演示
    双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然.
    出版社和图书的关系:Publishers——Books
    2.实体类
    n端
    Books.java

    public class Books {
    
        private Integer Id;
        private String Title;
        private String Author;
        private String ISBN;
        private int WordCount;
        private double UnitPrice;
        private String ContentDescription;
        //实体类类型属性
        private Publishers publisher;
        //忽略getter和setter方法
        ...
    }

    1端
    Publishers.java

    public class Publishers {
    
        private Integer id;
        private String Name;
        //集合属性
        private Set<Books> bks = new HashSet<>();
        //忽略getter和setter方法
        ...
    }

    3.映射文件
    n端:

    <hibernate-mapping package="com.withXml.bothmanyToone.entity" auto-import="false">
    
        <class name="Books" table="BOTH_BOOKS">
    
            <id name="Id" type="java.lang.Integer" access="field">
                <column name="ID" />
                <generator class="native" />
            </id>
    
            <property name="Title" type="java.lang.String">
                <column name="TITLE" />
            </property>
    
            <property name="Author" type="java.lang.String">
                <column name="AUTHOR" />
            </property>
    
            <property name="ISBN" type="java.lang.String">
                <column name="ISBN" />
            </property>
    
            <property name="WordCount" type="integer">
                <column name="WORD_COUNT"/>
            </property>
    
            <!-- 映射数据表字段你的类型,可以在property 里面使用type设置,也可以在column里面使用 sql-type-->
            <property name="UnitPrice">
                <column name="UNIT_PRICE" sql-type="double" />
            </property>
    
            <property name="ContentDescription" type="java.lang.String">
                <column name="CONTENT_DESCRIPTION" />
            </property>
    
            <!-- 配置多对一关联映射 -->
            <many-to-one name="publisher" class="Publishers" 
                column="PUBLISHER_ID" cascade="save-update"></many-to-one>
        </class>
    </hibernate-mapping>
    

    1端

    <hibernate-mapping package="com.withXml.bothmanyToone.entity" auto-import="false">
    
        <class name="Publishers" table="BOTH_PUBLISHERS">
    
            <id name="id" type="java.lang.Integer" access="field">
                <column name="ID" />
                <generator class="native" />
            </id>
    
            <property name="Name" type="java.lang.String">
                <column name="NAME" />
            </property>
    
            <!-- 
                cascade(级联)级联的意思是指两个对象之间的操作联运关系,对一个对象执行了操作之后,
                对其指定的级联对象也需要执行相同的操作,取值:all,none,save_update,delete。
                  1.all:代码在所有情况下都执行级联操作
                  2.none:在所有情况下都不执行级联操作
                  3.save-update:在保存和更新的情况下执行级联操作
                  4.delete:在删除的时候执行级联操作
                 inverse:属性设置为true代表一的一方不在拥有关联关系的控制权,而把控制权交给多的一方    
             -->
            <set name="bks" lazy="false" inverse="true" cascade="save-update,delete">
                <!-- <key>指定PUBLISHERS数据表的外键,使用的是BOOKS表中的PUBLISHER_ID列 -->
                <key column="PUBLISHER_ID"></key>
                <one-to-many class="Books"/>
            </set>
        </class>
    </hibernate-mapping>
    

    4.CRUD测试
    ①保存

    /**
         * 保存操作,保存1的一端
         */
        @Test
        public void testBothManyToOneSave(){
            //创建出版社对象
            Publishers publisher = new Publishers();
            publisher.setName("北京大学出版社");
    
            //新建图书对象
            Books book = new Books();
            book.setTitle("大学英语");
            book.setISBN("2018012103");
            book.setAuthor("李玲");
            book.setWordCount(10000);
            book.setUnitPrice(95.5);
            book.setContentDescription("无");
    
            //新建图书对象
            Books book2 = new Books();
            book2.setTitle("管理学");
            book2.setISBN("2018012104");
            book2.setAuthor("张青");
            book2.setWordCount(10000);
            book2.setUnitPrice(95.5);
            book2.setContentDescription("无");
    
            //双向维护关系
            //设置关联关系,指定一到多的关联关系  ,若由1端维护关系,会产生update语句,影响效率,
            //所以在1端映射文件中设置inverse="true",控制权交给n端维护关系
            publisher.getBks().add(book);
            publisher.getBks().add(book2);
    
            //设置关联关系,指定多到一的关联关系  
            book.setPublisher(publisher);
            book2.setPublisher(publisher);
    
            //执行保存,设置cascade级联属性之后,
            //只保存一端即可(哪一端设置级联属性,可以只保存那一段,两端都设置,则任意一端都可以执行保存)
            session.save(publisher);
        }

    ②保存2

        /**
         * 保存操作
         */
        @Test
        public void testBothManyToOneSave2(){
            //创建出版社对象
            Publishers publisher = new Publishers();
            publisher.setName("北京大学出版社");
    
            //新建图书对象
            Books book = new Books();
            book.setTitle("大学英语");
            book.setISBN("2018012103");
            book.setAuthor("李玲");
            book.setWordCount(10000);
            book.setUnitPrice(95.5);
            book.setContentDescription("无");
    
            //新建图书对象
            Books book2 = new Books();
            book2.setTitle("管理学");
            book2.setISBN("2018012104");
            book2.setAuthor("张青");
            book2.setWordCount(10000);
            book2.setUnitPrice(95.5);
            book2.setContentDescription("无");
    
            //双向维护关系
            //设置关联关系,指定一到多的关联关系  ,因为会产生update语句,影响效率
            //publisher.getBks().add(book);
            //publisher.getBks().add(book2);
    
            //设置关联关系,指定多到一的关联关系  
            book.setPublisher(publisher);
            book2.setPublisher(publisher);
    
            //执行保存,设置cascade级联属性之后,
            //只保存一端即可(哪一端设置级联属性,可以只保存那一段,两端都设置,则任意一端都可以执行保存)
            session.save(book);
            session.save(book2);
        }
    

    ③查询

    /**
         * 查询操作
         * 查询某出版社出版的图书
         */
        @Test
        public void testBothManyToOneGet(){
            Publishers publisher = (Publishers) session.get(Publishers.class, 1);
            Iterator<Books> iterator = publisher.getBks().iterator();
            System.out.println(publisher.getName() + "出版的图书有:");
            while(iterator.hasNext()){
                Books book = iterator.next();
                System.out.println(book.getTitle());
            }
        }

    ④修改

    /**
         * 修改操作
         * 把id为1的图书所对应的id为1出版社修改为id为2出版社
         */
        @Test
        public void testBothManyToOneUpdate(){
            //获取出版社对象
            Publishers publisher = (Publishers) session.get(Publishers.class, 1);
    
            //获取图书对象
            Books book = (Books) session.get(Books.class, 1);
            book.setPublisher(publisher);
    
            session.update(book);
        }
    

    ⑤n端删除

    /**
         * 删除操作,删除图书信息
         * 
         */
        @Test
        public void testBothManyToOneDelete(){
            Books book = (Books) session.get(Books.class, 12);
            session.delete(book);
    
        }

    ⑥1端删除

    /**
         * 删除操作,删除出版社信息,以及出版社出版的图书
         * 
         */
        @Test
        public void testBothManyToOneDelete2(){
            Publishers publisher = (Publishers) session.get(Publishers.class, 1);
            session.delete(publisher);
        }
    

    五.总结
    (双向n对1):其实就是单向n对1和单向1对n同时使用
    1端
    ①实体类:添加集合属性
    ②映射文件:使用<set> 元素映射集合属性,
    name属性指定映射的属性名
    inverse属性设置为true代表一的一方不在拥有关联关系的控制权,而把控制权交给多的一方
    <key> 元素指定外键,属性值要与n端的<many-to-one> 元素的column属性值一致,
    使用<one-to-many class="Books"/> 元素映射关联关系
    详细如下:

      <!-- 
    cascade(级联)级联的意思是指两个对象之间的操作联运关系,对一个对象
    执行了操作之后,对其指定的级联对象也需要执行相同的操作,
    取值:all,none,save_update,delete。
     1.all:代码在所有情况下都执行级联操作
     2.none:在所有情况下都不执行级联操作
     3.save-update:在保存和更新的情况下执行级联操作
     4.delete:在删除的时候执行级联操作
    inverse:属性设置为true代表一的一方不在拥有关联关系的控制权,
    而把控制权交给多的一方 
             -->
    <set name="bks" lazy="false" inverse="true" cascade="save-update,delete">
    <!-- <key>指定外键 -->
        <key column="PUBLISHER_ID" not-null="true"></key>
        <one-to-many class="Books"/>
    </set>

    n端:
    ①实体类:添加一个n端实体类型的属性
    ②映射文件:使用<many-to-one> 元素映射实体类型的属性,column属性指定外键,class指定关联的类的名字。
    详细如下:

    <!-- 配置多对一关联映射 -->
    <many-to-one name="publisher" class="Publishers"
             column="PUBLISHER_ID" cascade="save-update">
    </many-to-one>
  • 相关阅读:
    Pieczęć(模拟)
    【并查集】关押罪犯
    火车进栈
    独木舟上的旅行
    哈尔滨理工大学第八届程序设计团队赛K题
    [数学、递推]Everything Is Generated In Equal Probability
    [构造]triples I
    2019牛客第三场
    [DP]销售
    [哈夫曼树]猜球球
  • 原文地址:https://www.cnblogs.com/tengpengfei/p/10453954.html
Copyright © 2011-2022 走看看