hibernate 一对多映射 问题解决
现有主表Report 从表reportUser
<set name="reportUsers" cascade="all-delete-orphan" lazy="false"
inverse="false">
<key column="report_id_" />
<one-to-many />
</set>
看Report中的set配置
我的期望是由Report 即一的一端完全控制,那么可能会出现如下问题:
1.若 lazy="true" ,在执行set=report.getReportUser()是会出现no session错误,因此这里设为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它
会有 insert report_user_(...null,..)
然后才是 update report set ....
update 或 delete:先setnull,然后update delete
会有 update report_user_ set report_id_ =null where...
因此从表中的关联字段report_id_ 需要设为 可以为空 NULL
4. 对set的操作,不管是create,update,delete ,都需要从一的一方get
即report.getReportUser(),如果你new Set()给他,那么这个set将不被hibernate所管控,失去了控制, 会出现, you set is update by another tranc 你的set被另一个事务更改
因此,在report中的set 声明时 需要初始化,防止,create的时候 getReportUser 为空。
private Set<ReportUser> reportUser=new HashSet<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会自动删除
更多关于cascade inverse 等属性的用法,参见http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html