该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-05-25
http://robbin.iteye.com/blog/81990 引用 Hibernate不够易用,而且有一些明显的缺陷:one-to-one必须通过bytecode enhancement才能lazy loading;不支持多态关联 前半句,对于one-to-one关联,在Gavin King最新的《Java Persistance with Hibernate》中13.1节提到:必须是constrained="true"的关联才可以lazy loading,否则可以通过bytecode instrumentation来进行。那么为什么通过bytecode instrument来lazy loading是不好的呢? 对于后半句,为何说hibernate不支持多态关联? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-05-25
fredzhang 写道 看到robbin的文章有些不太明白
http://robbin.iteye.com/blog/81990 引用 Hibernate不够易用,而且有一些明显的缺陷:one-to-one必须通过bytecode enhancement才能lazy loading;不支持多态关联 前半句,对于one-to-one关联,在Gavin King最新的《Java Persistance with Hibernate》中13.1节提到:必须是constrained="true"的关联才可以lazy loading,否则可以通过bytecode instrumentation来进行。那么为什么通过bytecode instrument来lazy loading是不好的呢? 对于后半句,为何说hibernate不支持多态关联? constrained="true"限制太大了,byteocode增强你自己试试看能不能成功?和compiler,和JDK版本的关系很大,这种方式是很脆弱的,换个JDK版本部署就完蛋了。 多态关联Hibernate就是不支持阿,要不你写个Hibernate支持多态关联的例子给我看看? |
|
返回顶楼 | |
发表时间:2007-05-25
冒昧说一句,hibernate对于稍复杂的OO设计,映射起来确有麻烦,主要在多态上支持的不够完美。
简单例子: 04-05年一个项目设计,OperationLog对应的Target可以是多种不同Entity。 在JAVA对象层,有个LogTarget接口,多个实体类实现这个LogTarget: public interface LogTarget{ public Set getLogs(); } 在ORM层,当时的hibernate只能在Log的mapping上使用<any>映射, 而LogTarget上的Logs也可以用one-to-many加上wheresql解决。 到目前为止还算完美。 可是一旦实现了LogTarget的Entity出现子类,情况就混乱了。 无论如何配置,在子类的getLogs里面都会出现错误(有超类的log)。 ------------- 时间有些长,具体细节都忘掉了,大概情况是这样。 |
|
返回顶楼 | |
发表时间:2007-05-25
Gavin King的《Java Persistance with Hibernate》第7.3.1节不就是在讲多态关联吗?
bytecode增强和proxy都是用cglib实现的吧,那么为什么一种方式比较脆弱而另外一种不呢?前者在hibernate应当是在org.hibernate.bytecode.cglib下,后者应当是org.hibernate.proxy.cglib下,两者有一些区别,一个是用cglib 的 MethodInterceptor callback,另一个是cglib的Dispatcher callback。——如果我源码没看错的话... |
|
返回顶楼 | |
发表时间:2007-05-25
fredzhang 写道 Gavin King的《Java Persistance with Hibernate》第7.3.1节不就是在讲多态关联吗?
bytecode增强和proxy都是用cglib实现的吧,那么为什么一种方式比较脆弱而另外一种不呢?前者在hibernate应当是在org.hibernate.bytecode.cglib下,后者应当是org.hibernate.proxy.cglib下,两者有一些区别,一个是用cglib 的 MethodInterceptor callback,另一个是cglib的Dispatcher callback。——如果我源码没看错的话... 这是因为one-to-one关联的lazy loading无法使用cglib的动态增强,必须通过静态编译的方式增强。既然要通过静态编译操作字节码,那就和compiler的版本关系很大了。 多态关联关系Hibernate支持的很差,你对比一下RoR的多态关联就知道好的多态关联支持是怎么回事了。 |
|
返回顶楼 | |
发表时间:2007-05-25
原来RoR的多态关联跟Gavin King polymorphic associations的提法还是有不小差别的,从这个角度来说,hibernate的确不支持多态关联。
关于one-to-one关联的lazy loading,在constraint="false"的时候,无法使用cglib,在哪里有提及?我在网上没有搜到,除非得去读读源代码。ps hibernate的源代码,比起spring等其他框架,要复杂好多啊。 |
|
返回顶楼 | |
发表时间:2007-05-25
fredzhang 写道 原来RoR的多态关联跟Gavin King polymorphic associations的提法还是有不小差别的,从这个角度来说,hibernate的确不支持多态关联。
关于one-to-one关联的lazy loading,在constraint="false"的时候,无法使用cglib,在哪里有提及?我在网上没有搜到,除非得去读读源代码。ps hibernate的源代码,比起spring等其他框架,要复杂好多啊。 关于one-to-one关联的从方不能lazy loading是由one-to-one的机制造成的,比如user和contact是一对一,user是主,contact是从,约束依赖于user,那么在数据库中,contact表中应该有一个外键字段指向user表的主键。 当加载contact对象时,从contact表的记录中就可以得到user记录的id,这和多对一是一样的,就可以知道user对象是否存在,不存在则user为null,存在就生成代理对象,所以可以实现主方的延迟加载。 当加载user对象时,从user表记录中没有办法知道这个contact从方是否存在,它就不能确定是用null还是生成代理对象来代替contact对象,因为代理对象一定 != null,所以必须要查询contact表,查询这个从方是否存在。 如果要实现从方的延迟加载,自己写代理,那么这个代理应该加在主方user上,加在从方是没有用的,可以对user类的getContact()方法进行改造,执行该方法时查询contact表,如果记录不存在就返回null。 如果不自己写代理,直接在getContact()方法中采用上面的处理,不知行不行,好像也改变不了hibernate对从方预先加载的动作。 基于上面的情况,所以我现在一般不用one-to-one关联,倒不是一定要延迟加载,还有n+1次问题等等,处理起来比较麻烦,宁可用user到contact的多对一关联,contact为一方,虽然意义上好像反了,但是从user对象可以很方便的得到contact对象,实际上也都是从user来获取contact信息的,延迟加载也没问题。 |
|
返回顶楼 | |
发表时间:2007-05-25
janh说的很对,对user动态增强解决不了这个问题,所以只能静态增强,但是静态增强带来的限制太大。如果把外键保存在user表当中,指向contact,从关联关系上面来说,这是不对的。但是对于Hibernate来说没有办法。
对于RoR来说,不存在这个问题,这是因为ruby是动态语言,可以动态添加代码,所以用RoR的AR进行对象映射,比Hibernate要好用一些。 |
|
返回顶楼 | |
发表时间:2007-05-25
janh 写道 关于one-to-one关联的从方不能lazy loading是由one-to-one的机制造成的,比如user和contact是一对一,user是主,contact是从,约束依赖于user,那么在数据库中,contact表中应该有一个外键字段指向user表的主键。 当加载contact对象时,从contact表的记录中就可以得到user记录的id,这和多对一是一样的,就可以知道user对象是否存在,不存在则user为null,存在就生成代理对象,所以可以实现主方的延迟加载。 当加载user对象时,从user表记录中没有办法知道这个contact从方是否存在,它就不能确定是用null还是生成代理对象来代替contact对象,因为代理对象一定 != null,所以必须要查询contact表,查询这个从方是否存在。 如果要实现从方的延迟加载,自己写代理,那么这个代理应该加在主方user上,加在从方是没有用的,可以对user类的getContact()方法进行改造,执行该方法时查询contact表,如果记录不存在就返回null。 如果不自己写代理,直接在getContact()方法中采用上面的处理,不知行不行,好像也改变不了hibernate对从方预先加载的动作。 基于上面的情况,所以我现在一般不用one-to-one关联,倒不是一定要延迟加载,还有n+1次问题等等,处理起来比较麻烦,宁可用user到contact的多对一关联,contact为一方,虽然意义上好像反了,但是从user对象可以很方便的得到contact对象,实际上也都是从user来获取contact信息的,延迟加载也没问题。 你说的很对,当constrain="false"时,不能用代理。我只是对书上那句话的看法表示疑问,摘抄原句如下: 引用 Does lazy loading of one-to-one associations work? Lazy loading for one-to-one associations is sometimes confusing for new Hibernate users. If you consider one-to-one associations based on shared primary keys (chapter 7, section 7.1.1, “Shared primary key associations”), an association can be proxied only if it’s constrained="true". For example, an Address always has a reference to a User. If this association is nullable and optional, Hibernate first would have to hit the database to find out whether a proxy or a null should be applied—the purpose of lazy loading is to not hit the database at all. You can enable lazy loading through bytecode instrumentation and interception, which we’ll discuss later. |
|
返回顶楼 | |
发表时间:2007-05-27
为什么不在HIBERNATE中使用 本地SQL?
|
|
返回顶楼 | |