1

我有一个使用 Hibernate 作为持久性 ORM 的 Spring Web 应用程序。在某些时候,会向用户询问几个问题(按相关性按部分排序)以执行某些操作。

在我的存储库中,我通过以下 HQL 加载用户的问题:

StringBuilder hql = new StringBuilder();
hql.append("select question ")
   .append("from User as user ")
   .append("left join user.definition as definition ")
   .append("left join definition.sections as section ")
   .append("left join section.questions as question ")
   .append("where user.id = :user");

Query query = getQuery(hql.toString());
query.setParameter("user.id", userId);

return query.list();


这给出了这个非常奇怪的结果:

questions = {java.util.ArrayList@4629} size = 18
[0] = {model.Question@6692}"model.Question@49134043"
[1] = {model.Question@6693}"model.Question@ee01430"
[2] = {model.Question@6694}"model.Question@194d62f1"
[3] = {model.Question@6695}"model.Question@279ac931"
[4] = {model.Question@6696}"model.Question@230ec447"
[5] = {model.Question@6697}"model.Question@1e78234c"
[6] = {model.Question@6698}"model.Question@61556234"
[7] = {model.Question@6699}"model.Question@2ca275d8"
[8] = {model.Question@6700}"model.Question@5de6cecc"
[9] = {model.Question_$$_javassist_12@6701}"model.Question@5c12e33d"
[10] = {model.Question@6702}"model.Question@5c04e904"
[11] = {model.Question@6703}"model.Question@25c2cbee"
[12] = {model.Question@6704}"model.Question@17da89a0"
[13] = {model.Question@6705}"model.Question@c81739c"
[15] = {model.Question@6706}"model.Question@6cd0d2e"
[16] = {model.Question@6707}"model.Question@1c4a7f"
[17] = {model.Question@6708}"model.Question@415ed7e7"

有 2 件奇怪的事情需要注意:
1)ArrayList大小为 18,但由于某些非常奇怪的原因,第 14 个元素丢失了???
2)还有一个奇怪的地方是Question第9位的实例没有加载!它是 Hibernate 用于延迟加载的代理。但是所有其他实例都已完全加载(就像它应该像在 HQL 中定义的那样)。

我以前从未经历过这 2 件奇怪的事情,我检查了数据库中潜在的数据错误,但一切似乎都很好......

非常感谢所有帮助!

下面是“未初始化”对象的更详细视图:

[9] = {model.Question_$$_javassist_12@6701}"Question@218f5a04"
handler = {org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer@6739}
    interfaces = {java.lang.Class[1]@6745}
    constructed = true
    persistentClass = {java.lang.Class@2709}"class model.Question"
    getIdentifierMethod = null
    setIdentifierMethod = null
    overridesEquals = true
    componentIdType = null
    replacement = null
    entityName = {java.lang.String@6746}"model.Question"
    id = {java.lang.Long@6747}"31"
target = {model.Question@6748}"model.Question@218f5a04"
initialized = true
readOnly = false
unwrap = false
session =  {org.hibernate.internal.SessionImpl@6749}
"SessionImpl(PersistenceContext[entityKeys=
[EntityKey[model.Question#31],        EntityKey[model.Question#20], 
EntityKey[Question#17], EntityKey[model...
readOnlyBeforeAttachedToSession = null
sessionFactoryUuid = null
specjLazyLoad = false
group = null
questionType = null
text = null
uuid = {java.util.UUID@6741}"54e505a3-68ef-44a3-bf5e-e801e3443d79"
id = null
version = null
4

1 回答 1

2

我将尝试回答第一点(缺少第 14 个元素)。由于您在查询中使用左外连接,因此即使它们没有任何匹配,它也会为每个definitionand返回至少一行。在这种情况下,数据库将返回结果中的所有字段(因为您只从 中选择字段),我猜测 Hibernate 将其转换为.sectionquestionnullquestionArrayList

definition因此,如果您有一些没有任何section,或者如果您有一些section没有任何,请检查您的数据库question。这可以解释第一点。

您也可以尝试用内连接替换左外连接。这应该摆脱空条目。您决定在查询中使用外连接有什么原因吗?

至于第二点,我怀疑这条记录的数据级别存在一些不同,这将导致 Hibernate 只实例化一个代理而不是完整的对象。如果没有看到您的实体定义,很难说出什么。会不会是标识符以外的所有字段都是空的,所以 Hibernate 认为不需要实例化整个对象?

于 2013-09-24T20:43:46.673 回答