zoukankan      html  css  js  c++  java
  • Hibernate(或其它ORM)里的inverse用法详解,内容摘自Java web轻量级开发面试教程

        本文来是从 java web轻量级开发面试教程从摘录的。

        Inverse的英文含义是反转,在Hibernate中用来决定是由哪方来维护两个业务实体类之间的关联关系,具体而言,就是由哪方去设置这个被外键约束的字段值。

        它的默认值是false,也就是说,本端(比如inverse=false写在学生端,那么本端是学生,另外一方是课程)不“反转控制权”,这句别扭的话的另外一种说法是,本端维护关联关系。如果两边都不写,那么两端都维护。这样会造成问题,即新时因为两端都控制关系,因此可能会导致重复更新。

        注意,inverse仅仅是指定由谁来设置外键值,而不是用来设置级联操作,级联操作的方式由cascade来负责,很多人会混淆它们的含义和用法。

       这个例子所用到的数据表是Person表和Card表,其中Person表里包含ID、Name和Phone字段,而Card表里包含了CardID、PersonID、Bank和balance四个字段。   

        在hibernate.cfg.xml文件里,通过mapping resource来指定对应的映射文件,其中关键的代码如下:   

    1	<!-- 添加实体类的映射文件-->
    2	<mapping resource="Model/Card.hbm.xml" />
    3	<mapping resource="Model/Person.hbm.xml" />
    

        在Person.hbm.xml里,用如下代码来指定人(一方)和卡(多方)的关系,其中在人这一端,inverse是true。   

    1	<set name="cards" cascade="save-update" inverse="true">
    2	<key column="PersonID"/>
    3	<one-to-many class="Card"/>
    4	</set>
    

        在HibernateMain.java里,通过如下关键代码插入了一个人的信息。    

    1	//创建一张卡
    2	Card card1 = new Card();
    3	        card1.setCardID("Card123");
    4	        card1.setPersonID("Person123");
    5	        card1.setBank("Citi");
    6	        card1.setBalance(100f);
    7	//初始化一个人
    8	        Person person = new Person();
    9	        person.setID("Person123");
    10	        person.setName("Peter");
    11	        person.setPhone("123456");
    12	//在cards这个set里加入card1
    13	        Set<Card> cards = new HashSet<Card>();
    14	        cards.add(card1);
    15	        person.setCards(cards);
    16	//保存人的信息
    17	        session.save(person);
    18	        session.flush();
    

        运行后,在输出信息里能看到如下两条相关的插入语句:一条是插入Person信息,另一条是插入card信息。

    1     Hibernate: insert into Person (Name, Phone, ID) values (?, ?, ?)

    2     Hibernate: insert into Card (PersonID, Bank, Balance, Person, CardID) values (?, ?, ?, ?, ?)

        当把person.hbm.xml里的inverse设置成false时,能看到相关的语句里会多出一句update语句。

    1     Hibernate: insert into Person (Name, Phone, ID) values (?, ?, ?)

    2     Hibernate: insert into Card (PersonID, Bank, Balance, Person, CardID) values (?, ?, ?, ?, ?)

    3     Hibernate: update Card set PersonID=? where CardID=?

        原因是,当设置inverse为true时,Person这一端反转外键控制权,也就是由Card这端来管理外键,而在代码里我们仅仅是插入了Person,没有插入Card,所以就没有更新两个外键(PersonID和CardID)的操作。相反,当inverse为false时,管理外键控制权是在Person端,那么当插入Person时,Hibernate就需要额外的一句update语句来管理外键了。

        在一对多的例子里,inverse不论取什么值,对结果都没有影响,所以很容易让人忽视它的作用。

        在一对多的例子里,一般是让多方来管理外键控制权,比如一个人有100张开,那么如果由Person方来管理的话,无形中可能会多出100个update操作,效率上就不大好了。

        如果在一对多案例中,inverse只是影响效率的话,那么在多对多的例子中,inverse的设置就可能影响到数据。

        我们再来看个多对多的学生选课案例,其中一个学生可以选多门课,而一门课里可以有多个学生。在Student.hbm.xml里,描述多对多关系的语句里可加上inverse=“true”的语句。   

    1	<set name="courses" table="students_courses" inverse= "true" cascade="save-update">
    2	<key column="student_id"></key>
    3	<many-to-many class="Model.Course" column="course_id"></many-to-many>
    4	</set>
    

        在Course.hbm.xml里,不加任何关于inverse的语句,也就是说,在Student端反转外键控制权,把控制权交到Course端。

        在HibernateMain这个类里,通过如下代码让s1学生选修计算机课程。     

    1	        //设置一个学生,学号是1
    2	Student s1 = new Student();
    3	        s1.setStudentID("1");
    4	        s1.setStudentName("Peter");
    5	//设置多个课程
    6	        Course c1 = new Course();
    7	        c1.setCourseID("c1");
    8	        c1.setCourseName("Math");
    9	        Course c2 = new Course();
    10	        c2.setCourseID("c2");
    11	        c2.setCourseName("Java");
    12	        Course c3 = new Course();
    13	        c3.setCourseID("c3");
    14	        c3.setCourseName("C#");
    15	//设置计算机课程这个Set
    16	        Set<Course> computerCourses = new HashSet<Course>();
    17	        computerCourses.add(c2);
    18	        computerCourses.add(c3);
    19	//让s1这个学生选修计算机课程(也就是c2和c3课程)
    20	        s1.setCourses(computerCourses);
    21	//保存s1
    22	        session.save(s1);
    23	        session.flush();
    

        执行结果是,虽然能在Student和Course表里看到相关的学生和课程的记录,但在关键的描述学生选课关联表(students_courses)里,看不到任何关联记录。原因是已经通过设置inverse把外键管理权交给Course方了,这里仅仅是保存学生,并没有保存课程,所以没有插入外键的动作。如果要在students_courses表里插入外键关联,就需要在person.hbm.xml里设置inverse的值为false。

        所以,在多对多关联里,设置错了inverse值会导致结果出错,请大家根据具体项目的情况适当设值。

          

      

      

        

  • 相关阅读:
    [apue] FIFO:不是文件的文件
    [apue] 等待子进程的那些事儿
    [apue] popen/pclose 疑点解惑
    [apue] 使用 popen/pclose 的一点疑问
    [apue] 使用 poll 检测管道断开
    [apue] dup2的正确打开方式
    [apue] 管道原子写入量的一个疑问
    [apue] 测试管道容量的一些疑问
    【新阁教育】再也不用担心我的PLC通信不上了
    【新阁教育】三菱PLC的这个功能,真的很强大
  • 原文地址:https://www.cnblogs.com/JavaArchitect/p/7821644.html
Copyright © 2011-2022 走看看