Hibernate的inverse属性



Hibernate的inverse属性。

一个双向关联仅仅是在两端

简单地正确设置引用。然而,Hibernate 并没有足够的信息去正确地执行 INSERT 和

UPDATE 语句(以避免违反数据库约束),所以它需要一些帮助来正确的处理双向关联。把关联的

一端设置为 inverse 将告诉 Hibernate 忽略关联的这一端,把这端看成是另外一端的一个镜象

(mirror)。

 

 

说实话什么镜像的真是让人有点看不懂。后来照着书上做了做试验,也算是废了些功夫,大概觉得可以这样理解:inverse这个属性就是一个开关,来告诉Hibernate是不是根据映射文件中映射的集合中的对像数量(注意是数量,跟外键无关的字段发生变化将不会产生影响)的变化来自动维护主外键的关系。当inverse为false的时候,Hibernate就会自动维护主外键的关系,但这样有的时候会造成重复执行多余的update语句或当数据库的外键字段不允许为空的时候会导致插入失败,为true的时候,不管集合怎么变化,Hibernate将会忽视这些变化,需要在程序中手工维护主外键的关系(将集合中的对像的相应属性设为含有此集合的对像,这样hibernate才能正确设置外键的值,不然外键值将为null)。


但是当cascade属性被设成all-delete-orphan的时候是个例外,当被设成这个值的时候,即使inverse设成true,当集合中的对像被remove的时候会执行相应的delete语句,但它还是省略了将外键更新为null的相应的update语句,如果inverse为false,在删除前会执行先将外键更新成null的sql语句。

下面举几个例子:

order类含有customer属性,对应order表,其中cid字段为外键,参照customer表的主键,customer类,对应customer表,有一个order对像的set集合

例1:当new一个customer对像,然后new一个或多个order对像,然后将order对像添加到customer的集合中,不设置所有对像的ID,然后执行save方法,将会执行相应的insert语句,将customer和order插入到表中,如果没有设置order对像的customer属性,则插入的order对像的cid都将为null,如果cid字段不允许为null那将报错。如果inverse为false,最后还会针对插入的每条order记录执行相应的update `order` set cid=? where id=?,将其cid字段设置为customer对像的id的值,如果inverse为true,则不会执行order记录相应的update语句,这样就需要在程序中手动设置order对像的customer属性,来确保在插入order对像的时候能够插入正确的cid的值。

例2:当new一个customer对像,然后new一个或多个order对像,然后将order对像添加到customer的集合中,并且设置customer对像的的id,order对像的id设或不设都可,然后执行update方法来更新customer对像,没设id的order对像会执行insert语句,设了的会执行update语句,如果inverse设为false,Hibernate将执行update `order` set cid=null where cid=?,先将所有的cid为customer对像id值的order记录的cid值更新为null,然后再执行update `order` set cid=? where id=?,这样来确保数据库中所有cid为customer对像id值的order记录跟set集合中的记录完全相符,如果不执行update `order` set cid=null where cid=?,将有可能会有其他的cid为customer对像id值的记录存在,这样就跟set集合中的记录不相符,但如果只是想再增加几条相关的order记录,这样的更新方法会导致数据库原有的相关order记录全部丢失,如果inverse为true,则Hibernate不会执行最后两条update语句,为了使cid的数据正确,则需要设置order对像的customer属性。

例3:load一个customer对像及其相关的order记录,如果向customer的set集合中添加新的order对像,则Hibernate会对新增的order对像执行相应的update或insert语句,如果inverse为false,则Hibernate会针对这些增加的order记录执行update `order` set cid=? where id=?,如果inverse为true,则不会执行这些update语句,这就需要在程序中设置这些order对像的customer属性来保证外键值的正确。如果只是更改了set集合中原有的order对像中的和主外键关系无关的非customer属性,即使当inverse为false的时候,Hibernate只会按照更改后的order对像更改相应的order记录,但并不会执行维护主外键关系的update `order` set cid=? where id=?语句。

 

 

基于以上的这些例子,当使用Hibernate来映射一对多的时候为了确保不执行冗余的sql语句和数据的准确性,应该把映射文件中的集合元素的inverse属性设为true,然后在程序中手动的来维护主外键的关系,即在程序中将集合中的对像的相应属性设置成含有此集合的对像。