论坛首页 Java企业应用论坛

关于关联对象的级联删除的问题。(应用于“充血模型”)

浏览 4721 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-10-29  
用例是这样的:

现在有A、B两个对象,彼此关系是 A 1 : n B

换言之,A之中就有一个集合引用了B,现在我想通过调用 A.removeB(B b)方法,Hibernate就能透明的把B从数据库中删除掉,这样做的好处主要在于在“充血模型”中,领域对象有聚合根,所有对领域对象的操作必须由聚合根发起,上面的例子中,A是B的聚合根,因此需要删除B,则必须通过A发起。应用层的代码如下:


 
public class SomeService {
    public removeBFromA(Long bId,Long aId) {
        B b = bDao.get(bId);
        A a = aDao.get(aId);
        a.removeB(b);
    } 


我通过Hibernate设置了A、B的一对多关系,通过“mappedby”设置了B为主动方(主要是考虑插入数据的时候,不需要对B的外键调用多一次Update语句),casdaceType是ALL,但我发现,当删除A的时候,确实可以级联删除B,但当调用A.remove(B)的时候,只能把B的外键清空,并没有把B删除掉,而如果我尝试把B的外键的nullable设置为false,在调用b.setA(null)的时候,还会出现数据完整性异常,所以,根本无法通过A来发起对B的删除操作。(除非把B的DAO放置到A中,由A.removeB()方法显式调用DAO的方法删除B,但这就把持久化逻辑加入到领域对象中了,而持久化逻辑应该完全由应用层Servcie完成)。

于是,最终不得不把上面的代码改为:


 
public class SomeService {
    public removeBFromA(Long bId,Long aId) {
        B b = bDao.get(bId);
        A a = aDao.get(aId);
        a.removeB(b);
        bDao.remove(b); // 领域层的客户代码必须显式的删除B
    } 


上面的代码表面上没问题,但事实上,应用层必须显式的去删除B,这样做就不太优雅了,因为领域层把A管理B生命周期的细节泄漏到应用层了。

不知大家有没有什么好的办法解决这个问题。
   发表时间:2008-10-29  
补充一下,以下是 A.removeB()的实现逻辑

    public void removeB(B b) {
        getChildren().remove(b); // 在A属性的保存B的列表中把B清掉
         b.setParent(null); // 由于B是主动控制方,需要在这里显示把B中的A引用设置为null
    }


以下是在B当中的Hibernate设置

@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "A_FK" ,nullable=true)
	public A getParent() {
		return parent;
	}


以下是A当中的Hibernate设置:

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	public List<B> getChildren() {
		return children;
	}
0 请登录后投票
   发表时间:2008-10-29  
cascade 设置 all-delete-orphan
A的remove方法里面,将B从集合移除,同时将其parent设null
这样在session生命周期结束的时候,将会自动进行级联删除,你不需要调用dao的任何方法。
0 请登录后投票
   发表时间:2008-10-29  
Quake Wang 写道
cascade 设置 all-delete-orphan
A的remove方法里面,将B从集合移除,同时将其parent设null
这样在session生命周期结束的时候,将会自动进行级联删除,你不需要调用dao的任何方法。


请问orphan是什么意思呢?我使用的是J2EE的Persistent API,CascadeType并没有ORPHAN
0 请登录后投票
   发表时间:2008-10-29  
delete-orphan是Hibernate对JPA的扩展,你可以直接使用
http://www.hibernate.org/hib_docs/annotations/api/org/hibernate/annotations/CascadeType.html
0 请登录后投票
   发表时间:2008-10-29  
可以了,谢谢
0 请登录后投票
   发表时间:2008-10-29  
Quake Wang 写道
cascade 设置 all-delete-orphan
A的remove方法里面,将B从集合移除,同时将其parent设null
这样在session生命周期结束的时候,将会自动进行级联删除,你不需要调用dao的任何方法。

貌似用级联删除的时候,hibernate是一条条的删除,这点感觉不爽
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics