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

Мое приложение загружает объекты из Hibernate DAO с помощью OpenSessionInViewFilter, чтобы разрешить рендеринг.

В некоторых случаях я хочу внести небольшое изменение в поле -

Long orderId ...

link = new Link("cancel") {
    @Override public void onClick() {
        Order order = orderDAO.load(orderId);
        order.setCancelledTime(timeSource.getCurrentTime());       
    };

но такое изменение не сохраняется, поскольку OSIV не сбрасывается.

В этих случаях кажется позором вызывать orderDOA.save (order), но я не хочу заходить так далеко, как изменение FlushMode в OSIV.

Кто-нибудь нашел способ объявить «обработку запроса» (например, onClick) как требующий транзакции?

В идеале я предполагаю, что транзакция будет запущена на ранней стадии цикла запроса и зафиксирована OSIV, так что вся логика и рендеринг будут происходить в одной транзакции.

Ответы [ 2 ]

4 голосов
/ 26 мая 2011

Я обычно предпочитаю использовать дополнительный «служебный» уровень кода, который оборачивает базовый DAO логика и обеспечивает транзакции через @Transactional. Это дает мне лучшее разделение презентации и бизнес-логики и легче проверить.

Но так как вы уже используете OSIV, вы можете просто поместить некоторый AOP-перехватчик в код и есть ли у него flush ()?

1 голос
/ 26 мая 2011

Отказ от ответственности: я никогда не пробовал, но я думаю, что это сработает. Это также может быть немного больше кода, чем вы хотите написать. Наконец, я предполагаю, что ваши подклассы WebApplication SpringWebApplication. Ты со мной так далеко?

План заключается в том, чтобы сообщить Spring, что мы хотим запускать операторы вашего метода onClick в транзакции. Для этого нам нужно сделать три вещи.

Шаг 1: добавьте PlatformTransactionManager в вашу веб-страницу:

@SpringBean
private PlatformTransactionManager platformTransactionManager;

Шаг 2: создайте статическое TransactionDefinition на своей веб-странице, на которое мы позже будем ссылаться:

protected static final TransactionDefinition TRANSACTION_DEFINITION;
static {
    TRANSACTION_DEFINITION = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    ((DefaultTransactionDefinition) TRANSACTION_DEFINITION).setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
}

Не стесняйтесь изменять настройки TransactionDefinition и / или перемещать определение в общее местоположение в зависимости от ситуации. Это конкретное определение инструктирует Spring запускать новую транзакцию, даже если она уже запущена, и использовать максимальный уровень изоляции транзакции.

Шаг 3: добавить управление транзакциями в метод onClick:

link = new Link("cancel") {
    @Override 
    public void onClick() {
        new TransactionTemplate(platformTransactionManager, TRANSACTION_DEFINITION).execute(new TransactionCallback() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                Order order = orderDAO.load(orderId);
                order.setCancelledTime(timeSource.getCurrentTime());      
            }
        }
    } 
};

И это должно сработать!

...