Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Struts 2: проблема с множествами


Автор: MaxPayneC 19.6.2009, 11:38
Имеется код в JSP:
Код

<s:if test="graduate.getEducations().size() > 0">
<h3>Образование:</h3>
      <s:iterator value="graduate.getEducations().iterator()">
          <s:property value="getUniversity().getName()" />(<s:property value="getGraduationYear()"/>)<br />
      </s:iterator>
</s:if>


в соответствующем Action-классе есть метод getGraduate(), у возвращаемого им объекта - метод getEducations(), который возвращает Set<Education>. Проблема в том, что JSP считает множество пустым во всех случаях кроме одного: в методе execute action-класса был установлен брейкпоинт, и на graduate.getEducations().size() был сделан evaluate value. Тогда работает как должен. Кто-то сталкивался?

Автор: MisterCleric 19.6.2009, 11:45
должно быть так:
Код

<s:if test="!graduate.educations.empty">
<h3>Образование:</h3>
      <s:iterator value="graduate.educations">
          <s:property value="university.name" />(<s:property value="graduationYear"/>)<br />
      </s:iterator>
</s:if>


пробуй

Автор: MaxPayneC 19.6.2009, 11:52
Не работает. 
<s:if test="!graduate.educations.isEmpty"> всегда false
<s:if test="!graduate.getEducations().isEmpty()"> true, только если был сделан эвалуейт в экшн-классе

Автор: MisterCleric 19.6.2009, 12:12
Цитата

isEmpty


а я же написал 
Цитата

empty


ладно. покажи свой Action и его меппинг в struts.xml

Автор: MaxPayneC 19.6.2009, 12:42
Код

package com.vc.graduates.actions;

import com.vc.graduates.Graduate;
import com.vc.graduates.HibernateUtil;
import org.hibernate.Session;

/**
 * Created by IntelliJ IDEA.
 * User: maxpayne
 * Date: 09.06.2009
 * Time: 12:04:30
 * Action-класс, реализующий просмотр информации о выпускнике
 */
public class ShowGraduate extends AbstractAction
{
    /**
     * ID выпускника, анкета которого запрошена
     */
    private int graduate_id;
    /**
     * Экземпляр класса Graduate для передачи во view (ShowGraduate.jsp)
     */
    private Graduate graduate;

    /**
     * Загружает из базы информацию о выпускнике.
     * @return Если выпускник не найден в базе - Action.ERROR
     * Иначе Action.SUCCESS
     */
    public String execute()
    {
        Session hb_session = HibernateUtil.getSessionFactory().getCurrentSession();
        hb_session.beginTransaction();
        try
        {
            Graduate gr = (Graduate) hb_session.load(Graduate.class, getGraduate_id());
            setGraduate(gr);
        }
        catch (org.hibernate.ObjectNotFoundException ex)
        {
            addActionError("Запрошенный выпускник не найден.");
            return ERROR;
        }
        hb_session.getTransaction().commit();
        return SUCCESS;
    }

    public int getGraduate_id()
    {
        return graduate_id;
    }

    public void setGraduate_id(int graduate_id)
    {
        this.graduate_id = graduate_id;
    }

    public Graduate getGraduate()
    {
        return graduate;
    }

    public void setGraduate(Graduate graduate)
    {
        this.graduate = graduate;
    }
}


[xml]
        <action name="ShowGraduate" class="com.vc.graduates.actions.ShowGraduate">
            <result name="input">/GraduateInfo/NotFound.jsp</result>
            <result name="error">/GraduateInfo/NotFound.jsp</result>
            <result>/GraduateInfo/ShowGraduate.jsp</result>
        </action>
[/xml]


У сета нет метода empty(), только isEmpty()

Автор: MisterCleric 19.6.2009, 13:01
Цитата

У сета нет метода empty(), только isEmpty() 



вот мой работающий пример:
Код

<s:if test="!resultList.empty">
    <script type="text/javascript">
        //some JS-code
    </script>
</s:if>


Цитата

  Graduate gr = (Graduate) hb_session.load(Graduate.class, getGraduate_id());
            setGraduate(gr);


по-моему тут лишняя операция set.

Там же ситуация какая. Все проперти достаются через рефлексию исключением префиксов "get", "set"  а также "is" и приведением первой буквы в lowerCase ну и обратно с помощью такой движка как OJNL. Почитай доки как правильно надо с этим работать в кастом-тегах. 

default-interceptor-ref в студию!

Автор: MaxPayneC 19.6.2009, 13:08
Код

<s:if test="!resultList.empty">


А покажи джава-класс, плиз.

Добавлено через 7 минут и 15 секунд
Цитата
default-interceptor-ref в студию!

Если я правильно понял о чем ты, то вот фрагмент struts-default.xml

Код

...

        <default-interceptor-ref name="defaultStack"/>

        <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />


Автор: MisterCleric 19.6.2009, 13:32
Код

private List resultList;

 public String list() throws Exception {
        PageDTO result = facade.find(null, getPagination(), getFilter());
        saveResult(result, getFilter());
        return "list";
    }


 protected void saveResult(PageDTO result, Object filter) {
        resultList = result.getPageList();
    }

public List getResultList() {
     return resultList;
}


Цитата

  <default-interceptor-ref name="defaultStack"/>


со стэком вроде все-ок. Ну не понятно, что у тебя не так...

Автор: MaxPayneC 19.6.2009, 13:36
Возможно, какая-то проблема с set? :/
На ум приходят тока шаманские действия, чтото засунуть туда и вынуть в экшн-классе, раз код работает только после эвалуейта.

Добавлено через 4 минуты и 14 секунд
Добавил в код строки:

Код

Education edu = new Education(0);
graduate.getEducations().add(edu);
graduate.getEducations().remove(edu);


Заработало )

Автор: MisterCleric 19.6.2009, 13:54
Цитата

graduate.getEducations().add(edu);


так подожди, может у тебя эта коллекция LazyLoad? 
Понятно, что ее не будет после того, как ты сделал так
Цитата

  hb_session.getTransaction().commit();

Автор: MaxPayneC 19.6.2009, 13:59
В хибернейт-маппинге у education стоит lazy="false".
Я это написал зря? Сорри за этот вопрос, но я чтото не очень понял из доков, за что отвечает этот параметр :(

Автор: MisterCleric 19.6.2009, 14:03
давай дебажься и читай стэктрейс, что там пишеться кругом и как выглядит твой объект, после того, как ты вызвал commit();

Автор: MaxPayneC 19.6.2009, 14:12
Код

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.vc.graduates.Graduate.educations, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
    at org.hibernate.collection.PersistentSet.isEmpty(PersistentSet.java:169)
    at com.vc.graduates.actions.ShowGraduate.execute(ShowGraduate.java:49)


В дебаггере переменная осталась, эвалуейт ее сделать можно, сет с education-ами тоже можно посмотреть из дебаггера.

Добавлено через 2 минуты и 40 секунд
В маппинге класса Graduate было указано

Код

        <set name="educations" inverse="true" cascade="all-delete-orphan">
            <key column="graduate_id" />
            <one-to-many class="com.vc.graduates.Education" />
        </set>


вставил lazy="false", заработало. 

Ты не мог бы подсказать, где можно почитать про lazy initialization, так чтобы было доступно написано? В официальных доках к хибернейту чтото не могу понять смысл этой штуки :(

Автор: MisterCleric 19.6.2009, 14:16
ищи где-то по форуму я кому-то расписывал, как работать с этими LAZY

Автор: MaxPayneC 19.6.2009, 14:18
Окей. Спасибо за помощь )

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)