有用户和用户组两个表,需要使用hibernate做级联删除。映射文件如下:
Groups.hbm.xml
<class name="com.cms.entity.Groups" table="groups" catalog="cms">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="100" not-null="true" />
</property>
<property name="description" type="java.lang.String">
<column name="description" length="500" />
</property>
<property name="authority" type="java.lang.String">
<column name="authority" length="200" />
</property>
<set name="users" inverse="true" lazy="false" cascade="all-delete-orphan">
<key>
<column name="group_id" not-null="true" />
</key>
<one-to-many class="com.cms.entity.User" />
</set>
</class>
User.hbm.xml
<hibernate-mapping>
<class name="com.cms.entity.User" table="user" catalog="cms">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native"></generator>
</id>
<many-to-one name="groups" class="com.cms.entity.Groups" fetch="select">
<column name="group_id" not-null="true" />
</many-to-one>
<property name="name" type="java.lang.String">
<column name="name" length="50" not-null="true" />
</property>
<property name="password" type="java.lang.String">
<column name="password" length="200" not-null="true" />
</property>
<property name="qq" type="java.lang.String">
<column name="qq" length="50" />
</property>
<property name="phone" type="java.lang.String">
<column name="phone" length="50" />
</property>
<property name="postDate" type="java.util.Date">
<column name="post_date" length="0" not-null="true" />
</property>
<set name="articles" inverse="true" cascade="all-delete-orphan">
<key>
<column name="user_id" not-null="true" />
</key>
<one-to-many class="com.cms.entity.Article" />
</set>
</class>
</hibernate-mapping>
原本要做的是,删除用户组时将其下所属的用户全部删除;删除用户时,不对用户组进行更改。
结果过执行报错:deleted object would be re-saved by cascade (removedeleted object from associations)
感觉可能是cascade的配置问题,修改了下发现还是报错。后来我将Groups映射文件中<set>元素的lazy属性设置为true。删除成功!但是这样由于是延迟加载,就没法在页面中通过groups来获取User集合中的对象了(本来是想统计用户组中用户成员的个数)。于是还得修改。
查了文档弄明白了怎么回事。
原来cascade属性在lazy=true的时候不起作用(集合中对象还没初始化)。所以在删除User的时候,就不会触发对关联关系的维护。
而当lazy=false的时候,由于我们设置了cascade,那么删除User的时候会触发关系维护,此时虽然在user中已经将对应的Groups属性设置为null(删除前会先将外键设置为null)。但是由于Groups中的Set中仍然还保持着我们删除的User对象,所以触发关系维护的时候,这个User对象又会被重新保存到数据库中。造成了前面出现的异常。
当然,如果我们删除Groups的时候,如果没有将Set的cascade设置为all或delete,那么就会报错: Cannot delete or update a parent row:a foreign key constraint fails,因为groups删除了,User中对groups的外键引用怎么办?
解决的办法就是,如果不需要在groups中直接获取Set中的User对象,那么就把lazy设置为true就可以了。不设置cascade也可以,不过删除groups的时候就可能有问题了。或者通过代码,在删除之前将关联关系解除。
public void delete(User entity) {
entity.getGroups().getUsers().remove(entity);
entity.setGroups(null);
userDao.delete(entity);
}