我目前正在开发一款适用于Hibernate
(HQL)的产品,另一款适用于JPQL
的产品。尽管我喜欢从关系结构(数据库)到对象(Java类)的映射概念,但我并不相信它的性能。
示例:
爪哇:
public class Person{
private String name;
private int age;
private char sex;
private List<Person> children;
//...
}
我希望获得某个age
的属性Person
。一个有10个孩子的人(他一直很忙)。使用Hibernate或JPQL,您可以将此人作为对象进行检索。
HQL :
SELECT p
FROM my.package.Person as p
WHERE p.name = 'Hazaart'
我不仅会检索我不需要的人的其他属性,还会检索该人的所有孩子及其属性。他们也可能有孩子等等......这意味着在数据库级别访问的表将超过需要的数量。
结论:
我理解对象关系映射的优点。但是,在很多情况下,您似乎不需要某个对象的每个属性。特别是在复杂的系统中。看起来好处并不能证明性能损失是合理的。我一直都知道表现应该是主要关注点。
有人可以分享他们的意见吗?也许我正在以错误的方式看待它,也许我正在以错误的方式使用它......
答案 0 :(得分:1)
我不熟悉JPQL,但如果正确设置Hiernate,它将不会自动获取子项。相反,它将返回一个代理列表,如果访问它,它将透明地获取丢失的数据。
这也适用于对其他持久对象的简单引用。 Hibernate将创建一个仅包含ID的代理对象,并仅在访问时加载实际数据。 (“懒加载”)
这个有一些限制(比如持久化的类层次结构),但整体效果还不错。
顺便说一下,您应该使用List<Person>
来引用孩子。如果你指定一个特定的实现,我不确定Hibernate是否可以使用代理List。
更新:
在上面的例子中,Hibernate将加载属性名称,年龄和性别,并将创建一个最初不包含数据的List<Person>
代理对象。
一旦应用程序访问调用List的任何需要数据知识的方法,如childen.size()
或遍历列表,代理将调用Hibernate来读取子对象并填充List。作为Person
实例的cildren对象还将包含其子项的代理List<Person>
。
hibernate可能会在后台执行一些优化,比如可能在此会话中同时为其他Person对象加载子对象,因为它无论如何都在查询数据库。但是,这是否已完成以及扩展到每个属性是否可配置。
你也可以告诉hibernate永远不要对某些引用或类使用延迟加载,如果你确定以后需要它们,或者如果你在会话关闭后继续使用持久性oject。
请注意,如果会话不再处于活动状态,延迟加载当然会失败。例如,如果加载Person对象,不访问子列表,并关闭会话,则对children.size()
的调用将失败。
IIRC如果需要,hibernate会话类具有填充持久性对象中所有尚未加载的引用的方法。
最好阅读有关如何配置所有这些的hibernate文档。