2013-06-17 3 views
0

Этот фрагмент пропускает глобальный список testContainerCommand.testContainerLocationList. Для каждого местоположения он увидит, присутствует ли он в списке местоположений основного объекта testContainerCommand.testContainer.testContainerLocationList.Пользовательская функция JSTL всегда возвращает значение false

В обоих классах это свойство, которое выглядит так: private Set<TestContainerLocation> testContainerLocationList = new HashSet<TestContainerLocation>(0);.

Текущая отладка показывает, что testContainerCommand.testContainer.testContainerLocationList имеет два элемента

form.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> 
... 

Почему это всегда возвращение ложным? Должен ли я бросать объекты перед их сравнением?

Update # 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 

Update # 2

Web Fl ow file:

<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(); 
    } 

Update # 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; 
    } 


} 

Я нашел сайт, который, кажется, говорить о том, что ДПМ говорил: http://javarevisited.blogspot.ca/2011/02/how-to-write-equals-method-in-java.html

Вот содержание моего ранее сокращенного для каждого:

<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> 

Update # 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 - [[email protected], [email protected]]:[email protected] 
INFO : org.test.utils.Compare - [[email protected], [email protected]]:org.test.vto.TestCo[email protected] 
INFO : org.test.utils.Compare - [[email protected], [email protected]]:[email protected] 
INFO : org.test.utils.Compare - [[email protected], [email protected]]:[email protected] 
INFO : org.test.utils.Compare - [[email protected], [email protected]]:[email protected] 

Решение :

В соответствии с принятым решением мне просто пришлось переопределить методы equals и hashCode в моем классе TestContainerLocation.

@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; 
} 
+0

Откуда вы знаете, что оно возвращает false? Вы ничего не делаете внутри c: когда тег. Как определяются значения equals и hashCode? Каковы объекты в наборе и какой объект вы передаете в containsSet()? –

+0

Вы исключали JSTL/EL из подозреваемого, выполнив 's.contains (o)' как обычное Java-приложение? Есть одна довольно очевидная базовая ошибка начинающих Java, которая может вызвать эту проблему, но вы нигде в вопросе явно не исключили ее из-за причины. – BalusC

+0

@ Первый параметр jb-nizet - это Set , второй - один экземпляр TestContainerLocation. Я также добавил вывод HTML-комментариев, который показывает, что это ложь ... вот что я основал. – TekiusFanatikus

ответ

1

Вы должны опубликовать свой класс TestContainerLocation, что было бы полезно для ответа на этот вопрос. Похоже, что вы не имеете переопределенных equals() или hashCode(). TestContainerLocation будет использовать реализации Object для них, поэтому ваш пример кода Java из обновления 1 будет работать (они на самом деле одни и те же объекты), но если вы извлекаете объекты из спящего режима в разное время, они не будут Object.equal , и ваш вызов из JSP вернет false.

+0

См. Обновление # 3, я добавил свой класс TestContainerLocation. – TekiusFanatikus

+0

мой класс TestContainerLocation имеет ссылку на TestContainer для удовлетворения требований к отношениям «многие ко многим» в спящем режиме. Должно ли переопределение учитывать это или я могу опустить это для контекста, я использую метод equals? – TekiusFanatikus

+0

спасибо за помощь – TekiusFanatikus

Смежные вопросы