Как правильно использовать LoadableDetachableModel в веб-приложении на основе Wicket, Spring, Hibernate? - PullRequest
4 голосов
/ 11 августа 2011

Я занимаюсь разработкой веб-приложения на основе Hibernate, Spring и Wicket.

До сих пор я реализовывал бизнес-объекты и слой постоянства. Транзакция управляется перехватчиком транзакции среды Spring. Таким образом, каждый метод классов DAO заключен в транзакцию. Реализация этого вместе с модульным тестом была простой.

Теперь я перехожу к части веб-приложения, где я также использую Spring для внедрения зависимостей. Вместе с аннотациями @SpringBean платформы Wicket я внедряю DAO в компоненты Wicket. Но так как я довольно новичок в Wicket, я немного застрял, когда использую подходящую модель для своих бизнес-объектов, когда передаю их компонентам Wicket.

Я пробовал LoadableDetachableModel, но столкнулся с некоторыми проблемами. Я получил одну страницу, чтобы создать новый или отредактировать существующий бизнес-объект в зависимости от входных параметров страницы. Если в параметрах есть идентификатор, то соответствующий бизнес-объект должен быть загружен из базы данных. При отсутствии параметров следует создать новый бизнес-объект. Часть, в которой объект должен быть отредактирован, работает довольно хорошо, но когда должен быть создан новый объект, и я заполняю веб-форму и нажимаю сохранить, я получаю исключение NullPointerException. После некоторой отладки я обнаружил, что LoadableDetachableModel не может вернуть экземпляр бизнес-объекта, так как переопределенный метод load () не может загрузить объект из базы данных, поскольку он еще не был сохранен и поэтому не имеет идентификатора.

Так что теперь мне интересно, как решить эту проблему. Является ли LoadableDetachableModel правильным выбором? Целесообразно ли разделить форму на две взаимозависимые формы, и каждая форма использует свою модель. Таким образом, только страница редактирования / форма использует LoadableDetachableModel?

Ответы [ 2 ]

2 голосов
/ 12 августа 2011

Хорошее объяснение этой и некоторых связанных с этим проблем Игорь Вайнберг может найти в блоге Wicket In Action .

Последний бит на этой странице имеет дело с этой проблемой, в основном не , использующим LoadableDetachableModel, но реализующим AbstractEntityModel, который позволяет более полный контроль.

0 голосов
/ 06 августа 2014

Справочная документация по калитке 6.x> 11 Модели и формы калитки> 11.6 Съемные модели описывает это следующим образом:

Теперь в качестве примера возможного использования LoadableDetachableModel, мы построим модель, предназначенную для работы с объектами, управляемыми через JPA.Чтобы понять следующий код, необходимы базовые знания JPA, даже если мы не будем вдаваться в подробности этого стандарта.

Следующая модель предоставляется только в качестве примера и не предназначена для использования в производствесреда.Важные аспекты, такие как управление транзакциями, не принимаются во внимание, и вы должны переработать код, прежде чем подумать об его использовании.

public class JpaLoadableModel<T> extends LoadableDetachableModel<T> {

    private EntityManagerFactory entityManagerFactory;
    private Class<T> entityClass;
    private Serializable identifier;
    private List<Object> constructorParams;

    public JpaLoadableModel(EntityManagerFactory entityManagerFactory, T entity) {
        super();

        PersistenceUnitUtil util = entityManagerFactory.getPersistenceUnitUtil();

        this.entityManagerFactory = entityManagerFactory;
        this.entityClass = (Class<T>) entity.getClass();
        this.identifier = (Serializable) util.getIdentifier(entity);

        setObject(entity);
    }

    @Override protected T load() {
        T entity = null;

        if(identifier != null) {
            EntityManager entityManager = entityManagerFactory.createEntityManager();
            entity = entityManager.find(entityClass, identifier);
        }
        return entity;
    }

    @Override protected void onDetach() {
        super.onDetach();

        T entity = getObject();
        PersistenceUnitUtil persistenceUtil = entityManagerFactory.getPersistenceUnitUtil();

        if(entity == null) return;

        identifier = (Serializable) persistenceUtil.getIdentifier(entity);
    }
}

Конструктор модели принимает в качестве входных данных два параметра: реализацию интерфейса JPA javax.persistence.EntityManagerFactory для управления объектами JPA и объект, который должен обрабатываться этой моделью.Внутри своего конструктора модель сохраняет класс сущности и ее идентификатор (который может быть нулевым, если сущность еще не сохранена).Эти две информации требуются для извлечения объекта в более позднее время и используются методом загрузки.

onDetach отвечает за обновление идентификатора объекта до отсоединения.Идентификатор может измениться при первом сохранении сущности (JPA генерирует новый идентификатор и присваивает его сущности).Обратите внимание, что эта модель не несет ответственности за сохранение каких-либо изменений, произошедших с объектом-сущностью до его отсоединения.Если мы не хотим потерять эти изменения, мы должны явно сохранить сущность до того, как произойдет этап отсоединения.

Поскольку модель этого примера содержит ссылку на EntityManagerFactory, используемая реализация должна быть Serializable.

...