<;h:选择一个功能表>;和从hibernate延迟加载

<;h:选择一个功能表>;和从hibernate延迟加载,hibernate,jsf,jsf-2,lazy-loading,Hibernate,Jsf,Jsf 2,Lazy Loading,在我的JSF应用程序中,我有一段非常简单的代码。我希望用户从中的集合中选择一个值: {bean.value}的类型为区域,{dao.valuesFromDb}返回区域的列表。问题是,bean中的Region是从hibernate延迟加载的,它将其包装在一些包装器中,类看起来像my.package.Region\u$$\ uJavassist_15@25183 如果#{bean.value}设置了一些值,那么如果它在值列表(#{dao.valuesFromDb})中,应该在页面上预先选择它。问

在我的JSF应用程序中,我有一段非常简单的代码。我希望用户从
中的集合中选择一个值:


{bean.value}
的类型为
区域
{dao.valuesFromDb}
返回
区域的列表。问题是,bean中的
Region
是从hibernate延迟加载的,它将其包装在一些包装器中,类看起来像
my.package.Region\u$$\ uJavassist_15@25183

如果
#{bean.value}
设置了一些值,那么如果它在值列表(
#{dao.valuesFromDb}
)中,应该在页面上预先选择它。问题是它是通过
equals
方法检查的,该方法返回
false
,因为类型不同


如何解决这个问题?有没有可能强迫JSF不使用
等于
,而是自己处理这个比较?重写
equals
从而忽略类型是一个非常糟糕的主意,因为它会破坏
equals
对称性。

在这种情况下,我会通过在
bean
中急切地获取
区域来避免这个问题


与简单地获取JSF想要进行比较的信息相比,使用equals()将导致代码不够清晰。正如您所指出的,这可能会产生意想不到的后果。

我们决定通过重写“equals”方法来解决这个问题。重要的技巧是永远不要在equals方法中直接引用外部对象的属性,而是始终使用getter。然后Hibernate似乎从javassist对象中挖掘出正确的值

在您的例子中,Region equals方法应该如下所示:

@Override
public boolean equals(Object obj) {
    if (this == obj) {return true;}
    if (obj == null) {return false;}
    if (!(obj instanceof Region)) {return false;}

    Region region = (Region) obj;

    if ((name == null) && (region.getName() != null)) {return false;}  // Do NOT use 'region.name' here
    else if (!name.equals(region.getName())) {return false;}           // Do NOT use 'region.name' here
    return true;
}

您可以通过调用(控制器的)操作中的
区域
getter来预加载bean,而不是将fetch类型更改为EAGER。即:只需调用
bean.getRegion()
方法


这样您就不会得到LazyInitializationException(如果您得到的是LazyInitializationException)。

我就是不能。我们有许多依赖实体,并且在单个查询中超过了连接的限制。我们不得不将一些急切的加载更改为懒惰。有趣的问题。当我遇到类似的问题(deepgraph)时,我会分别对相关对象进行水合处理,并将其设置在目标bean上。由于有多个集合,我不得不这样做以避免笛卡尔连接。笛卡尔连接也有一些问题。你能分享一些解释它的链接吗?你可以从Hibernate文档开始。第14.3节包括“通过在一个查询中联合获取多个集合,可以创建笛卡尔积,因此在这种情况下要小心。联合获取多个集合角色可能会对行李映射产生意外结果,因此在这种情况下,建议用户在制定查询时自行决定。”这与我的经验相符,通常需要大量的尝试和错误才能找到正确的解决方案。
@Override
public boolean equals(Object obj) {
    if (this == obj) {return true;}
    if (obj == null) {return false;}
    if (!(obj instanceof Region)) {return false;}

    Region region = (Region) obj;

    if ((name == null) && (region.getName() != null)) {return false;}  // Do NOT use 'region.name' here
    else if (!name.equals(region.getName())) {return false;}           // Do NOT use 'region.name' here
    return true;
}