zoukankan      html  css  js  c++  java
  • hibernate一对多关系采用外键映射时使用inverse的几种情况

    hibernate关系的维护比较头疼,遂总结下做个备份。

    什么时候维护关系:当关联双方对象有一方的属性发生变化时。

    举例:一个用户有多个账户,类User和类Account是一对多的双向关联关系。

    User类:

    public class User {

        private Long oid;

        private String uid;

        private String name;

        //关联属性

        private Set accts = new HashSet();

    ......

    }

    Account类:

    public class Account {

        private Long oid;

        private String acctNo;

        private double bal;

        //关联属性

        private User owner;

    ......

    }

    mq_user:

    mysql> desc mq_user;

    +-----------+--------------+------+-----+---------+----------------+

    | Field     | Type         | Null | Key | Default | Extra          |

    +-----------+--------------+------+-----+---------+----------------+

    | OID       | bigint(20)   | NO   | PRI | NULL    | auto_increment |

    | USER_ID   | varchar(255) | NO   | UNI | NULL    |                |

    | USER_NAME | varchar(255) | NO   |     | NULL    |                |

    +-----------+--------------+------+-----+---------+----------------+

    mq_acct2

    mysql> desc mq_acct2;

    +--------+--------------+------+-----+---------+----------------+

    | Field | Type         | Null | Key | Default | Extra          |

    +--------+--------------+------+-----+---------+----------------+

    | OID    | bigint(20)   | NO   | PRI | NULL    | auto_increment |

    | ACCTNO | varchar(255) | NO   | UNI | NULL    |                |

    | BAL    | double       | NO   |     | NULL    |                |

    | FID    | bigint(20)   | YES | MUL | NULL    |                |

    +--------+--------------+------+-----+---------+----------------+

    映射文件:

    User.hbm.xml:

    <set name = "accts" inverse = "false" >

               <key column="FID" />

               <one-to-many class="Account" />

    </set>

    Account.hbm.xml:

    <many-to-one name = "owner"

                  class = "User"

                  column = "FID"/>

     

    如果:Session s = HbnUtil.getSession();

         s.beginTransaction();

         Account acct1 = new Account("a01", 5000.0);

         User user = new User("u01","jack");

         user.getAccts().add(acct1);

         s.save(user);

         s.save(acct1);

         s.getTransaction().commit();

    结果:Hibernate:

        insert

        into

            mq_user

            (USER_ID, USER_NAME)

        values

            (?, ?)

    Hibernate:

        insert

        into

            mq_acct2

            (ACCTNO, BAL, FID)

        values

            (?, ?, ?)

    Hibernate:

        update

            mq_acct2

        set

            FID=?

        where

            OID=?

     

    说明:一对多双向关联中默认多的一方inverse=”false”,也就是说由多的一方维护关系。

    这里把一的一方的inverse也改为false,并且在代码中不写acct1.setOwner(user)是为了测试一的一方是如何维护关系的。

    在执行了insert into 语句以后,紧接着执行的update语句就是一的一方在维护关系。

    从执行的过程还可以看出,维护关系的动作实际上是update而不是insert操作。

    总结:1,多的一方总是维护且必须维护关系(many-to-one中没有inverse属性),一的一方可以选择维护或不维护。

    ---------------------------------------------------------------------

    如果:Session s = HbnUtil.getSession();

         s.beginTransaction();

         Account acct1 = new Account("a01", 5000.0);

         User user = new User("u01","jack");

         user.getAccts().add(acct1);

         s.save(user);

         s.getTransaction().commit();

    结果:Hibernate:

        insert

        into

            mq_user

            (USER_ID, USER_NAME)

        values

            (?, ?)

    Hibernate:

        update

            mq_user

        set

            USER_ID=?,

            USER_NAME=?

        where

            OID=?

    Hibernate:

        update

            mq_acct2

        set

            FID=?

        where

            OID=?

    org.hibernate.TransientObjectException:

     

    说明:去掉了对acct1的保存。抛异常。

          inverse是关系维护而不是级联操作(通过配置cascade属性可以让user被保存时级联acct1一起被保存),关系维护只会update

    总结:2,关系维护只做update,不搞级联,所以要注意维护的数据是否已经在数据库中。

             除非做了级联create或者数据库中有被维护的数据,否则是要抛异常滴。

    ---------------------------------------------------------------------

    如果:Account acct1 = new Account("a01", 5000.0);

         User user = new User("u01","jack");

         user.getAccts().add(acct1);

         s.save(user);

         s.save(acct1);

         user.setName("aaaaa");

    结果:Hibernate:

        insert

        into

            mq_user

            (USER_ID, USER_NAME)

        values

            (?, ?)

    Hibernate:

        insert

        into

            mq_acct2

            (ACCTNO, BAL, FID)

        values

            (?, ?, ?)

    Hibernate:

        update

            mq_user

        set

            USER_ID=?,

            USER_NAME=?

        where

            OID=?

    Hibernate:

        update

            mq_acct2

        set

            FID=?

        where

            OID=?

    说明:因为user是一个持久化对象(session保存过),所以在user属性发生改变时,session会监测user属性是否改变并在改变后自动执行update mq_user。但不管acct1属性是否改变,也不管username改变是否影响到了他和acct1的关系,都会再维护一次。

    ---------------------------------------------------------------------

    如果:Account acct1 = new Account("a01", 5000.0);

         User user = new User("u01","jack");

         user.getAccts().add(acct1);

         s.save(user);

         s.save(acct1);

         acct1.setBal(999);

    结果:

    Hibernate:

        insert

        into

            mq_user

            (USER_ID, USER_NAME)

        values

            (?, ?)

    Hibernate:

        insert

        into

            mq_acct2

            (ACCTNO, BAL, FID)

        values

            (?, ?, ?)

    Hibernate:

        update

            mq_acct2

        set

            ACCTNO=?,

            BAL=?,

            FID=?

        where

            OID=?

    Hibernate:

        update

            mq_acct2

        set

            FID=?

        where

            OID=?

    说明:因为acct1是持久化对象,所以session在发现acct1bal发生改变后会自动执行

    update mq_acct2语句。随后负责维护关系的user一方会再维护一次关系。

    ------------------------------------------------------------------------------------

    如果:Account acct1 = new Account("a01", 5000.0);

         User user = new User("u01","jack");

         user.getAccts().add(acct1);

         acct1.setOwner(user);

         s.save(user);

         s.save(acct1);

         acct1.setBal(999);

    结果:Hibernate:

        insert

        into

            mq_user

            (USER_ID, USER_NAME)

        values

            (?, ?)

    Hibernate:

        insert

        into

            mq_acct2

            (ACCTNO, BAL, FID)

        values

            (?, ?, ?)

    Hibernate:

        update

            mq_acct2

        set

            ACCTNO=?,

            BAL=?,

            FID=?

        where

            OID=?

    Hibernate:

        update

            mq_acct2

        set

            FID=?

        where

            OID=?

    说明:如果双方是双向关联又各自都维护关系,那么当需要维护时会各自维护一次。

    总结:3,实际运行时的对象如果不知道对方对象的存在(没有关联)就不会维护关系。

         4,只要任意一方属性变了就维护,不管这个变更是否影响到了关系。

     
  • 相关阅读:
    (十)android项目中,通用布局的对话框的实现。
    devexpress控件layoutview特效之一旋转木马的实现
    devexpress设置皮肤、字体以及折叠菜单、伸缩Panel的实现
    devexpress设置系统全局字体(含工具栏字体)
    devexpress表格控件gridcontrol实现纵向标头
    中文繁简互换以及获取中文字符串首字母
    devexpress显示缓冲滚动条与实现类似QQ消息推送效果
    gridcontrol显示行号,总行,打印,导出Excel,设置标头及内容居中方法
    devexpress表格控件gridcontrol特殊应用(一)——实现禁用特定行(附源代码)
    devexpress表格控件gridcontrol设置隔行变色、焦点行颜色、设置(改变)显示值、固定列不移动(附源码)
  • 原文地址:https://www.cnblogs.com/mabaishui/p/1586205.html
Copyright © 2011-2022 走看看