Как использовать одну транзакцию для просмотра страницы Wicket / Spring? - PullRequest
0 голосов
/ 28 мая 2011

Мой предыдущий вопрос Как обернуть отображение страницы Wicket в транзакции Spring / Hibernate? заставило меня задуматься о разграничении транзакций в Wicket.

Хотя этот пример был легко решен путем перемещения бизнес-логики на уровень, управляемый Spring, в других местах это невозможно.

У меня есть общий класс DAO, реализованный с помощьюHibernate, с

public class HibernateDAO<T> implements DAO<T> {

    protected final Class<T> entityClass;
    private final SessionFactory sessionFactory;

    @Transactional
    public T load(Serializable id) {
        return (T) getSession().get(entityClass, id);
    }

    @Transactional
    public void saveOrUpdate(T object) {
        getSession().saveOrUpdate(object);
    }

}

и общей моделью для его извлечения

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

    private DAO<T> dao;
    private final Serializable id;

    public DAOEntityModel(DAO<T> dao, Serializable id) {
        this.dao = dao;
        this.id = id;
    }

    public <U extends Entity> DAOEntityModel(DAO<T> dao, U entity) {
        this(dao, entity.getId());
    }

    public Serializable getId() {
        return id;
    }

    @Override
    protected T load() {
        return dao.load(id);
    }

}

Теперь у меня есть минимальная форма, которая меняет сущность

public class ScreenDetailsPanel extends Panel {

    @SpringBean(name="screenDAO") private DAO<Screen> dao;

    public ScreenDetailsPanel(String panelId, Long screenId) {
        super(panelId);
        final IModel<Screen> screenModel = new DAOEntityModel<Screen>(dao, screenId);
        Form<Screen> form = new Form<Screen>("form") {
            @Override protected void onSubmit() {
                Screen screen = screenModel.getObject();
                dao.saveOrUpdate(screen);
            }};
        form.add(
            new TextField<String>("name", new PropertyModel<String>(screenModel, "name")));
        add(form);
    }    
}

Покахорошо - спасибо за поддержку!

Итак, моя проблема в следующем - когда форма отправлена, PropertyModel загрузит screenModel, что произойдет в транзакции, описанной @Transactional dao.load (id),Фиксация изменений произойдет, когда (другая) транзакция, запущенная для dao.saveOrUpdate (object), будет зафиксирована.В промежутке между этими периодами все ставки отключены, так что объект может больше не существовать в БД для фиксации.

Я никогда не до конца уверен с кодом БД и транзакциями.Должен ли я просто отмахнуться от этого, как от маловероятного, хотя я мог бы построить другие более сложные, но более опасные сценарии?Если нет, я не вижу, как разграничить логику всей страницы в одной транзакции, к чему мой инстинкт подсказывает мне, к чему я должен стремиться.

Ответы [ 2 ]

3 голосов
/ 28 мая 2011

Как правило, вы решаете эту проблему, помещая аннотацию @Transactional в класс уровня обслуживания, используемый вашим кодом внешнего уровня, который охватывает операции DAO - так, чтобы загрузка и сохранение происходили в одной транзакции. Другими словами, вы можете решить эту проблему, создав слой кода между формой и кодом DAO, «сервисный уровень», который обеспечивает логику бизнес-уровня и скрывает присутствие DAO от уровня представления.

0 голосов
/ 01 июня 2011

Я еще не реализовал это, но я почти уверен, что решение @ireddick в Как управлять сохранением JPA в формах Wicket? ленивого запуска tx в цикле запроса Wicket - это лучшее решение здесь. Я собираюсь принять этот прокси, чтобы остановить переполнение стека, заставляя меня принять ответ.

...