hibernate用了好久了,却还是一知半解,对很多概念都不是很清楚,今天又碰到了inverse的问题,总不能一次一次的应付下去,查了好久资料,终于对这个概念有了自己的理解,记笔记如下。
inverse只能出现在hibernate中的一对多one-to-many和多对多many-to-many中,他表示了由哪一方来维护双方的关系,其实在many-to-one中也有这个inverse,只不过该值是false,且不能更改而已。inverse=true表示由对方来维护关系,而inverse=false表示由自己来维护关系,下面解释一下维护关系的概念。为了简单起见,在这儿配置没有使用级联设置。
假设有两张表parent和child,parent和child是一对多的关系,一个parent可以有多个child,而多个child可以属于一个parent,假设XML配置如下:
<class name="Parent" table="parent">
...
<set name="children" table="child" lazy="true" cascade="none" inverse="true">
<key column="parentID"></key>
<one-to-many class="Child"/>
</set>
</class>
<class name="Child" table="child">
...
<many-to-one name="parent" class="one2many.Parent" cascade="none">
<column name="parentID"/>
</many-to-one>
</class>
在parent的child中的inverse=true,这就表示由child来维护关系,也就是说在保存parent时候,是不会去维护与child的关系,而只有在保存child实体的时候才会把关系写入到数据库中。以下用例子说明:
1.inverse=true,代码如下:
Parent parent = new Parent();
Child child = new Child();
parent.getChildren().add(child);
child.setParent(parent);//如果没有这一句,会插入两条记录,但是child的parentID字段为空值
session.save(parent);
session.save(child);//在此处会保存关系
session.flush();
以下代码会生成SQL如下:
Hibernate: insert into parent (name, ID) values (?, ?)
Hibernate: insert into child (name, parentID, ID) values (?, ?, ?)
2.inverse=false,代码如下:
清单2.1
Parent parent = new Parent();
Child child = new Child();
parent.getChildren().add(child);
child.setParent(parent);//注释一
session.save(parent);
session.save(child);//在此处会保存关系
session.flush();
生成的SQL如下:
Hibernate: insert into parent (name, ID) values (?, ?)
Hibernate: insert into child (name, parentID, ID) values (?, ?, ?)
Hibernate: update child set parentID=? where ID=?
如果我们把注释一处的内容去掉或者注释,即代码如下:
清单2.2
Parent parent = new Parent();
Child child = new Child();
parent.getChildren().add(child);
//child.setParent(parent);//注释一
session.save(parent);
session.save(child);//在此处会保存关系
session.flush();
此时生成的SQL如下:
Hibernate: insert into parent (name, ID) values (?, ?)
Hibernate: insert into child (name, parentID, ID) values (?, ?, ?)
Hibernate: update child set parentID=? where ID=?
此时好像看起来生成的代码是一样的,而且结果也是一样的,但实际上在第一处的时候生成插入child的时候,parentID是有值的,但是在注释掉后插入child的时候,parentID的值是null,如果在数据库中有外键约束的时候肯定会出错。清单2.1中生成的SQL和inverse=true进行比较,发现多了一条update语句,这个update是由parent创建的,因为parent也负责管理关系,这样导致多了一次操作。清单2.2中的代码在插入child的时候,首先会给parentID赋空值,然后再由parent负责更新child的parentID字段。
以上就是个人对inverse的简单理解,如果有什么不对的地方,欢迎大家指正。