Object 关系映射和性能
Object Relational mapping and performance
我目前正在开发一款适用于 Hibernate
(HQL) 的产品和一款适用于 JPQL
的产品。尽管我喜欢从关系结构(数据库)映射到 object(Java class)的概念,但我对性能不满意。
示例:
Java:
public class Person{
private String name;
private int age;
private char sex;
private List<Person> children;
//...
}
我想获取某个Person
的属性age
。一个人10children(他一直很忙)。使用 Hibernate 或 JPQL,您可以将此人检索为 object.
HQL:
SELECT p
FROM my.package.Person as p
WHERE p.name = 'Hazaart'
我不仅会检索我不需要的人的其他属性,还会检索该人的所有 children 及其属性。他们可能还有 children 等等...这意味着在数据库级别访问的表比需要的要多。
结论:
我了解 Object 关系映射的优势。然而,在很多情况下,您似乎不需要某个 object 的每个属性。特别是在一个复杂的系统中。看起来这些优势几乎不能证明性能损失是合理的。我一直认为性能应该是主要关注点。
任何人都可以分享他们的意见吗?也许我看错了,也许我用错了...
我不熟悉 JPQL,但如果您正确设置 Hiernate,它不会自动获取 children。相反,它将 return 一个代理列表,如果被访问,它将透明地获取丢失的数据。
这也适用于对其他持久性 object 的简单引用。 Hibernate 将创建一个代理 object,仅包含 ID,并仅在访问时加载实际数据。 ("lazy loading")
这当然有一些局限性(比如持久的 class 层次结构),但总体效果很好。
顺便说一句,你应该使用 List<Person>
来引用 children。如果您指定特定的实现,我不确定 Hibernate 是否可以使用代理列表。
更新:
在上面的示例中,Hibernate 将加载属性名称、年龄和性别,并将创建一个 List<Person>
代理 object 最初不包含任何数据。
一旦应用程序访问调用需要了解数据的列表的任何方法,例如 childen.size()
或遍历列表,代理将调用 Hibernate 来读取 children objects 并填充列表。孩子 object 是 Person
的实例,也将包含 他们的 children.[=16= 的代理 List<Person>
]
hibernate 可能会在后台执行一些优化,比如同时为其他人 object 加载 children,而这可能在这个 session 中,因为它无论如何都在查询数据库。但是是否这样做以及在多大程度上可以根据属性进行配置。
你也可以告诉 hibernate 不要对某些引用或 class 使用 lazy-loading,如果你确定你以后会需要它们,或者如果你继续使用持久对象一次session 已关闭。
请注意,如果 session 不再处于活动状态,延迟加载当然会失败。例如,如果您加载一个 Person 对象,不访问 children 列表,并关闭 session,例如对 children.size()
的调用将失败。
IIRC hibernate session class 有方法在需要时填充持久对象中的所有 not-yet-loaded 引用。
最好阅读有关如何配置所有这些的休眠文档。
我目前正在开发一款适用于 Hibernate
(HQL) 的产品和一款适用于 JPQL
的产品。尽管我喜欢从关系结构(数据库)映射到 object(Java class)的概念,但我对性能不满意。
示例:
Java:
public class Person{
private String name;
private int age;
private char sex;
private List<Person> children;
//...
}
我想获取某个Person
的属性age
。一个人10children(他一直很忙)。使用 Hibernate 或 JPQL,您可以将此人检索为 object.
HQL:
SELECT p
FROM my.package.Person as p
WHERE p.name = 'Hazaart'
我不仅会检索我不需要的人的其他属性,还会检索该人的所有 children 及其属性。他们可能还有 children 等等...这意味着在数据库级别访问的表比需要的要多。
结论:
我了解 Object 关系映射的优势。然而,在很多情况下,您似乎不需要某个 object 的每个属性。特别是在一个复杂的系统中。看起来这些优势几乎不能证明性能损失是合理的。我一直认为性能应该是主要关注点。
任何人都可以分享他们的意见吗?也许我看错了,也许我用错了...
我不熟悉 JPQL,但如果您正确设置 Hiernate,它不会自动获取 children。相反,它将 return 一个代理列表,如果被访问,它将透明地获取丢失的数据。
这也适用于对其他持久性 object 的简单引用。 Hibernate 将创建一个代理 object,仅包含 ID,并仅在访问时加载实际数据。 ("lazy loading")
这当然有一些局限性(比如持久的 class 层次结构),但总体效果很好。
顺便说一句,你应该使用 List<Person>
来引用 children。如果您指定特定的实现,我不确定 Hibernate 是否可以使用代理列表。
更新:
在上面的示例中,Hibernate 将加载属性名称、年龄和性别,并将创建一个 List<Person>
代理 object 最初不包含任何数据。
一旦应用程序访问调用需要了解数据的列表的任何方法,例如 childen.size()
或遍历列表,代理将调用 Hibernate 来读取 children objects 并填充列表。孩子 object 是 Person
的实例,也将包含 他们的 children.[=16= 的代理 List<Person>
]
hibernate 可能会在后台执行一些优化,比如同时为其他人 object 加载 children,而这可能在这个 session 中,因为它无论如何都在查询数据库。但是是否这样做以及在多大程度上可以根据属性进行配置。
你也可以告诉 hibernate 不要对某些引用或 class 使用 lazy-loading,如果你确定你以后会需要它们,或者如果你继续使用持久对象一次session 已关闭。
请注意,如果 session 不再处于活动状态,延迟加载当然会失败。例如,如果您加载一个 Person 对象,不访问 children 列表,并关闭 session,例如对 children.size()
的调用将失败。
IIRC hibernate session class 有方法在需要时填充持久对象中的所有 not-yet-loaded 引用。
最好阅读有关如何配置所有这些的休眠文档。