hibernate 一对多映射 问题解决
现有主表Report从表reportUser
<setname="reportUsers"cascade="all-delete-orphan"lazy="false"
inverse="false">
<keycolumn="report_id_"/>
<one-to-manyclass="ReportUser"/>
</set>
看Report中的set配置
我的期望是由Report即一的一端完全控制,那么可能会出现如下问题:
1.若lazy="true",在执行set=report.getReportUser()是会出现nosession错误,因此这里设为lazy="false"
2.若cascade设为“save-update”或其他,那么你会发现,删除Report时,并没有把reportUser删除,只是把reportUser的report_id_字段设为了null
3.若1,2没问题,如果你的数据库中report_user_表的关联字段report_id_设为not-null,
则,更新或删除set的时候,会报不能为null的错误。
这是因为hibernate执行update,create,delete都分为2步,先插入null,或设为null,再update,
可以把hql打出来看
create:先插入null,然后update它
会有insertreport_user_(...null,..)
然后才是updatereportset....
update或delete:先setnull,然后updatedelete
会有updatereport_user_setreport_id_=nullwhere...
因此从表中的关联字段report_id_需要设为可以为空NULL
4.对set的操作,不管是create,update,delete,都需要从一的一方get
即report.getReportUser(),如果你newSet()给他,那么这个set将不被hibernate所管控,失去了控制,会出现,yousetisupdatebyanothertranc你的set被另一个事务更改
因此,在report中的set声明时需要初始化,防止,create的时候getReportUser为空。
privateSet<ReportUser>reportUser=newHashSet<ReportUser>();
5.操作示例
create:
set=report.getReportUser();
set.add(reportUser1);
set.add(reportUser2);
session...update(report);
reportUser1,2中不必要设置report或是reportId了,因为,此set已经是从report取出来的,会自动关联
update:
set=report.getReportUser();
set.clear();//先clear
set.add(reportUser1);
set.add(reportUser2);
session...update(report);
delete:
session...delete(report);
直接删除reort即可,reportUser会自动删除
更多关于cascadeinverse等属性的用法,参见http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html