在我的JSF应用程序中,我有一段非常简单的代码。我希望用户从<h:selectOneMenu>
中的集合中选择一个值:
<h:selectOneMenu value="#{bean.value}">
<f:selectItems value="#{dao.valuesFromDb}" />
</h:selectOneMenu>
#{bean.value}
的类型为Region
,#{dao.valuesFromDb}
会返回Regions
的列表。问题是,bean中的Region
是从hibernate延迟加载的,它将它包装在一些包装器中,类看起来像my.package.Region_$$_javassist_15@25183
。
如果#{bean.value}
设置了一些值,则应在页面上预选它,如果它在值列表中(#{dao.valuesFromDb}
)。问题是由equals
方法检查,该方法返回false
,因为类型不同。
如何解决这个问题?是否有可能强制JSF不使用equals
,但不知何故自己处理这种比较?覆盖equals
所以忽略类型是恕我直言,这是非常糟糕的主意,因为它可以打破equals
对称性。
答案 0 :(得分:0)
在这种情况下,我会急切地在Region
中抓取bean
来完全避免这个问题。
使用equals()进行填充将导致代码远不如简单地获取JSF想要进行比较的信息。正如你所指出的那样,它可能会产生意想不到的后果。
答案 1 :(得分:0)
我们决定在Override'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;
}
答案 2 :(得分:0)
您可以通过调用转发到视图的操作(控制器)中的Region
getter来预加载bean,而不是将获取类型更改为EAGER。即:只需调用bean.getRegion()
方法。
这样你就不会得到LazyInitializationException(如果那是你得到的)。