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