此代码段循环遍历testContainerCommand.testContainerLocationList
. 对于每个位置,它将查看它是否存在于主对象的位置列表中 testContainerCommand.testContainer.testContainerLocationList
。
在这两个类中,它的属性如下所示:private Set<TestContainerLocation> testContainerLocationList = new HashSet<TestContainerLocation>(0);
.
当前调试显示testContainerCommand.testContainer.testContainerLocationList
有两个项目
表单.jsp
<p>Number of locations: ${fn:length(testContainerCommand.testContainer.testContainerLocationList)}</p>
<!-- currently shows 2 -->
<c:forEach items="${testContainerCommand.testContainerLocationList}" var="loc" varStatus="status">
<!-- ${cfn:containsSet(testContainerCommand.testContainer.testContainerLocationList,loc)} -->
<c:choose>
<c:when test="${cfn:containsSet(testContainerCommand.testContainer.testContainerLocationList,loc)}">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
</c:forEach>
我的 custom.tld 文件:
<function>
<name>containsSet</name>
<function-class>org.test.utils.Compare</function-class>
<function-signature>boolean containsSet(java.util.Set,java.lang.Object)
</function-signature>
</function>
我的 Custom.java 文件:
public class Compare {
public static boolean containsSet(Set s, Object o){
return s.contains(o);
}
}
TestContainer XML Hibernate 映射:
...
<set name="testContainerLocationList" table="test_container_location_lookup"
inverse="false" lazy="false" fetch="select" cascade="all">
<key>
<column name="id" not-null="true"/>
</key>
<many-to-many entity-name="org.test.vto.TestContainerLocation">
<column name="location_id" not-null="true" />
</many-to-many>
</set>
...
为什么它总是返回假?在比较它们之前我是否必须投射对象?
更新#1
我运行了以下测试代码:
public class Main {
public static void main(String[] args) {
Session session = HibernateUtil.getSessionFactory().openSession();
try{
List<TestContainerLocation> testContainerLocationList = session.createQuery("from TestContainerLocation").list();
TestContainer testContainer = (TestContainer)session.createQuery("from TestContainer where id = 12").list().get(0);
for(TestContainerLocation l: testContainerLocationList){
System.out.println(Compare.containsSet(testContainer.getTestContainerLocationList(), l));
}
}
catch(RuntimeException e){
e.printStackTrace();
}
session.close();
}
}
哪个输出(如预期):
true
true
false
false
false
更新#2
网络流文件:
<view-state id="form" view="/dbtest/form" model="testContainerCommand">
<on-entry>
<evaluate
expression="testContainerAction.getTestContainer(testContainerCommand, flowRequestContext)" />
<evaluate
expression="testContainerAction.getTestContainerLocationList(testContainerCommand, flowRequestContext)" />
</on-entry>
<transition on="submit" to="saveForm" />
<transition on="display" to="display" />
</view-state>
TestContainerAction.java
public void getTestContainer(TestContainerCommand cmd, RequestContext requestContext) throws Exception{
HttpServletRequest request = (HttpServletRequest) requestContext.getExternalContext().getNativeRequest();
//get param
String id = request.getParameter("id");
//param present
if(! StringUtils.isEmpty(id) && StringUtils.isNumeric(id)){
cmd.setTestContainer(testContainerDao.getTestContainerById(Long.parseLong(id)));
}
//no param
else{
TestContainer t = new TestContainer();
t.setTestContainerType(new TestContainerType());
t.setTestContainerLocationList(new HashSet<TestContainerLocation>(0));
cmd.setTestContainer(t);
}
cmd.setTestContainerTypeList(testContainerTypeDao.getTestContainerTypeList());
cmd.setTestContainerLocationList(testContainerLocationDao.getTestContainerLocationList());
}
public List<TestContainerLocation> getTestContainerLocationList(TestContainerCommand cmd, RequestContext requestContext) throws Exception{
cmd.setTestContainerLocationList(testContainerLocationDao.getTestContainerLocationList());
return cmd.getTestContainerLocationList();
}
更新#3
TestContainerLocation 类:
public class TestContainerLocation implements Serializable {
/**
*
*/
private static final long serialVersionUID = -1381290537575465609L;
private Integer locationId;
private String locationName;
private Set<TestContainer> testContainer = new HashSet<TestContainer>(0);
public Integer getLocationId() {
return locationId;
}
public void setLocationId(Integer locationId) {
this.locationId = locationId;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public Set<TestContainer> getTestContainer() {
return testContainer;
}
public void setTestContainer(Set<TestContainer> testContainer) {
this.testContainer = testContainer;
}
}
我找到了一个似乎在谈论 DPM 所说内容的网站:http: //javarevisited.blogspot.ca/2011/02/how-to-write-equals-method-in-java.html
这是我之前缩写的forEach的内容:
<ul>
<c:forEach items="${testContainerCommand.testContainerLocationList}" var="loc" varStatus="status">
<!-- ${cfn:containsSet(testContainerCommand.testContainer.testContainerLocationList,loc)} -->
<c:choose>
<c:when test="${cfn:containsSet(testContainerCommand.testContainer.testContainerLocationList,loc)}">
<li><input type="checkbox" id="location${loc.locationId}" name="location"
value="${loc.locationId}"
checked="checked" />
<label for="location${loc.locationId}">${loc.locationName}</label></li>
</c:when>
<c:otherwise>
<li><input type="checkbox" id="location${loc.locationId}" name="location"
value="${loc.locationId}" />
<label for="location${loc.locationId}">${loc.locationName}</label></li>
</c:otherwise>
</c:choose>
</c:forEach>
</ul>
更新#4
新的比较函数,对传入的对象执行简单的 toString():
public class Compare {
private static Logger logger = Logger.getLogger(Compare.class);
public static boolean containsSet(Set s, Object o){
logger.info(s.toString()+":"+o.toString());
return s.contains(o);
}
}
所述日志记录的输出:
INFO : org.test.utils.Compare - [org.test.vto.TestContainerLocation@6c5bdfae, org.test.vto.TestContainerLocation@6a7be687]:org.test.vto.TestContainerLocation@13de6be9
INFO : org.test.utils.Compare - [org.test.vto.TestContainerLocation@6c5bdfae, org.test.vto.TestContainerLocation@6a7be687]:org.test.vto.TestContainerLocation@6f7e982f
INFO : org.test.utils.Compare - [org.test.vto.TestContainerLocation@6c5bdfae, org.test.vto.TestContainerLocation@6a7be687]:org.test.vto.TestContainerLocation@60396ed8
INFO : org.test.utils.Compare - [org.test.vto.TestContainerLocation@6c5bdfae, org.test.vto.TestContainerLocation@6a7be687]:org.test.vto.TestContainerLocation@5a9c5842
INFO : org.test.utils.Compare - [org.test.vto.TestContainerLocation@6c5bdfae, org.test.vto.TestContainerLocation@6a7be687]:org.test.vto.TestContainerLocation@4e668387
解决方案:
根据公认的解决方案,我只需要覆盖我的 TestContainerLocation 类中的 equals 和 hashCode 方法。
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
TestContainerLocation in = (TestContainerLocation) obj;
return getLocationId() == in.getLocationId()
&& (getLocationName() == in.getLocationName()
|| (getLocationName() != null && getLocationName().equals(in.getLocationName())));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getLocationId() == null) ? 0 : Long.valueOf(getLocationId()).hashCode());
result = prime * result + ((getLocationName() == null) ? 0 : getLocationName().hashCode());
return result;
}