论坛首页 Java版 Hibernate

对ORM JPA设计上的几个疑问

浏览 3022 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (4) :: 隐藏帖 (0)
作者 正文
时间:2008-07-01

    近来做JPA的simple时,不时遇到了几个疑问,我不知为什么JPA的设计者要这样设计一个ORM。

  1.  为什么jpa的merge,要首先去数据库找一下数据,后等到事务提交方生成update的的脚本,我还因此以为自己做的unitTest出错。先去查一下数据库这一步,为什么不能略去呢,虽然在大部分情况下,他应该能在二级缓存中找到这条数据,但,我还是实在看不出理由来
  2. 为什么删除一条数据,一定要受控状态下的实体。这就照成了要删除一条记录时,需要再去查询一次,获得一个受控实体后,方能删除。这又是为什么,我怎么一点也没有感觉到它的好处呢。

 

   
时间:2008-07-01
[quote] 为什么jpa的merge,要首先去数据库找一下数据,后等到事务提交方生成update的的脚本,我还因此以为自己做的unitTest出错。先去查一下数据库这一步,为什么不能略去呢,虽然在大部分情况下,他应该能在二级缓存中找到这条数据,但,我还是实在看不出理由来[/quote]
merge操作主要目的将非受管对象的状态同步到受管对象中。受管对象构造过程session-》二级缓存-》数据库,发生数据库查找很正常。

[quote]为什么删除一条数据,一定要受控状态下的实体。这就照成了要删除一条记录时,需要再去查询一次,获得一个受控实体后,方能删除。这又是为什么,我怎么一点也没有感觉到它的好处呢。[/quote]
删除[quote]时相关事件的触发,级联删除,缓存更新都依赖于受管对象,所以要先有受管对象。

[quote]你可能最想弄明白受管对象有什么好?[/quote]
有 自动同步,级联,懒加载,缓存,事件这些优点。
   
0 请登录后投票
时间:2008-07-01
guoshiguan 写道

merge操作主要目的将非受管对象的状态同步到受管对象中。受管对象构造过程session-》二级缓存-》数据库,发生数据库查找很正常。

我知道merge操作主要目的,但为什么要查找了,是设计二级缓存时必要的吗,为什么不直接更新数据库就好,我实在不觉复查找是个正常的事,可能是因为我对二级缓存的实现方式还不了解吧。

guoshiguan 写道
时相关事件的触发,级联删除,缓存更新都依赖于受管对象,所以要先有受管对象。

受管对象的好处要当然知道,但问题是,为什么删除一定要受管对象,级联删除为什么会依赖于受管对象呢。

guoshiguan 写道
你可能最想弄明白受管对象有什么好?
有 自动同步,级联,懒加载,缓存,事件这些优点。

我不是不明白受管对象的好处,我只是不明白,为什么直接做的事,为什么删除操作要变成受管对象以后才能做。
   
0 请登录后投票
时间:2008-07-01
如果删除前不检查一下,删除一个不存在的对象也正常执行了也很Orz
   
0 请登录后投票
时间:2008-07-01
引用
我知道merge操作主要目的,但为什么要查找了,是设计二级缓存时必要的吗,为什么不直接更新数据库就好,我实在不觉复查找是个正常的事,可能是因为我对二级缓存的实现方式还不了解吧。

很多人的答案可能都是在更新之前,但是我觉得答案应该是在更新之后。

引用
受管对象的好处要当然知道,但问题是,为什么删除一定要受管对象,级联删除为什么会依赖于受管对象呢。

受控对象存在于JVM内存中,但是数据库已经没有对应的这条数据了,接下来会发生什么?
另外你是如何配置级联的?不要告诉我你没有配置而是自己手动处理
   
0 请登录后投票
时间:2008-07-01
Joo 写道

很多人的答案可能都是在更新之前,但是我觉得答案应该是在更新之后。

想想我也觉得应该是之后吧,要不更新不成功怎么办。

Joo 写道

受控对象存在于JVM内存中,但是数据库已经没有对应的这条数据了,接下来会发生什么?
另外你是如何配置级联的?不要告诉我你没有配置而是自己手动处理

我的simple还没有做到那一步的说,还没有进行过级联操作过,不过,你这么说倒是有点道理。
不过,实际开发中要删除的实体应该多半是脱管对象吧,也就是说,我要用脱管对象里的ID用JPA的find方法获得一个受控对象,再来对这个对象进行删除,这整个流程怎么都会让人觉得很奇怪吧。
   
0 请登录后投票
时间:2008-07-01
guoshiguan 写道

我知道merge操作主要目的,但为什么要查找了,是设计二级缓存时必要的吗,为什么不直接更新数据库就好,我实在不觉复查找是个正常的事,可能是因为我对二级缓存的实现方式还不了解吧。
时相关事件的触发,级联删除,缓存更新都依赖于受管对象,所以要先有受管对象。

因为事实jpa的设计就不想即刻做数据库同步,merge后,仍可以更改对象的状态,只在主动flush或auto flush需要时去同步。另外级联merge时,需要知道那些关联对象需要merge,这也需要知道对象的状态,所以需要获取对象的状态(也即是受管对象),虽然受管对象可能跟数据库不一致,但这一点不影响,不一致情况下后面的更新检查抛出异常,或事务提交异常。删除也同理。
另外如hibernate的事务性和readwrite二级缓存设计,在事务成功时,对事务中所发生变化的受管对象进行更新。

举个merge的例子:
Student{
@OneToMany
List books
}
加入一detached的books有books1,books2,而受管对象有books1,books2,book3
那么要如何做数据库同步呢?
第一种方式:
update Book set studentId = '' where studentId = 'abc',
update Book set student = 'studentId' where id = 'booksId1'
update Book set student = 'studentId' where id = 'booksId2'
或是只做一次
update Book set student = null where id = 'booksId3'
二级缓存又如何将book3与student的关系去除呢?

从设计上说,符合以下条件,可只产生update语句:
1.只有单向关系。
2.二级缓存的设计使用更新则清除。
3.id产生策略采用自动方式(因为jpa规定merge时需要检查对象是否存在)。
   
0 请登录后投票
时间:2008-07-02
引用

我要用脱管对象里的ID用JPA的find方法获得一个受控对象,再来对这个对象进行删除,这整个流程怎么都会让人觉得很奇怪吧。


ORM框架说:你都不告诉俺你要删哪个? 我怎么知道删哪个?
   
0 请登录后投票
时间:2008-07-04
nihongye 写道
有 自动同步,级联,懒加载,缓存,事件这些优点。


因为Hibernate也实现了JPA,我就拿Hibernate说事了。

除了懒加载和部分事件,没看出其他东西有什么用途,基本上都是和性能调优对立的,我认为放弃那些特性也没什么不好的。

还有就是缓存,除了一级缓存还有点用以外,二级缓存基本无用,即使用了,效率还不如自己控制全局的缓存控制来的灵活,全局的控制还能用上更多的其他缓存技术,而不是局限在Hibernate中,局限在Java的JVM中(Memcached,不是缓存页面)。

托管对象,造成巨大的Hiberanate学习成本,28原则,Hibernate中80%的陡峭学习曲线就是由这些20%的东西造成的,然后在性能调优上更是浪费不少时间,这和原本提高整个效率的做法背道而驰的,增加设计成本、增加调试成本、增加维护交接成本。

有这点时间,几行编码早就解决了,比如级联就是典型例子。随着对Hibernate的理解越深刻,越发现由级联、托管对象、二级缓存越是太理想化。
   
0 请登录后投票
时间:2008-07-04
guoshiguan 写道
guoshiguan 写道

merge操作主要目的将非受管对象的状态同步到受管对象中。受管对象构造过程session-》二级缓存-》数据库,发生数据库查找很正常。

我知道merge操作主要目的,但为什么要查找了,是设计二级缓存时必要的吗,为什么不直接更新数据库就好,我实在不觉复查找是个正常的事,可能是因为我对二级缓存的实现方式还不了解吧。

guoshiguan 写道
时相关事件的触发,级联删除,缓存更新都依赖于受管对象,所以要先有受管对象。

受管对象的好处要当然知道,但问题是,为什么删除一定要受管对象,级联删除为什么会依赖于受管对象呢。

guoshiguan 写道
你可能最想弄明白受管对象有什么好?
有 自动同步,级联,懒加载,缓存,事件这些优点。

我不是不明白受管对象的好处,我只是不明白,为什么直接做的事,为什么删除操作要变成受管对象以后才能做。


很简单,只要存在二级缓存的可能,那更新和删除对象,势必要先对比二级缓存中的数据是否需要同步。

你问得很好,完全可以不用级联、二级缓存、merge这些功能,没有必要。

我认为只有在一个事务的范围中,hibernate才有利用价值(比如一级缓存),而且要充分利用。跨事务的话,除了open session in view,其他的都免了吧。
   
0 请登录后投票
论坛首页 Java版 Hibernate

跳转论坛:
JavaEye推荐