<;h:选择一个功能表>;和从hibernate延迟加载
在我的JSF应用程序中,我有一段非常简单的代码。我希望用户从<;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})中,应该在页面上预先选择它。问
中的集合中选择一个值:
{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;
}