2013-04-17 3 views
0

Я встречаюсь с некоторыми странными поведением в управляемых весной транзакциях. Это приложение Spring MVC. Я привязываю объекты непосредственно к веб-уровню. Я загружаю постоянный объект из базы данных для редактирования, используя следующий код уровня сервиса, который вызывается из метода, аннотированного с помощью @ModelAttribute.Spring JPA Transaction

@Transactional(readOnly = true) 
@PreAuthorize("#id == authentication.principal.id or hasRole('ROLE_ADMIN')") 
public User findById(Long id) { 
    return repository.findOne(id); 
} 

Когда форма отправлена, данные привязаны к этому отдельному объекту. В рамках проверки я запрашиваю базу данных для проверки того, что адрес электронной почты, указанный для пользователя, уникален.

@Transactional(readOnly = true) 
public boolean isEmailAddressUnique(String emailAddress, Long userId){ 
    return repository.checkEmailAddressUnique(emailAddress, userId) == 0; 
} 

На данный момент, перед выполнением этого запроса Hibernate пытается очистить предварительно загруженный отдельностоящий объект, который я не понимаю. Очевидно, что это приводит к исключению, если адрес электронной почты не уникален.

Я использую OpenEntityManagerinViewFilter, однако я бы ожидал, что это должно иметь значение FlushMode NEVER, возможно, нет.

Если я удаляю атрибут @Transactional из isEmailAddressUnique(), то флеш не возникает, и все работает так, как ожидалось, что, я полагаю, решает проблему, однако я хотел бы понять, что здесь происходит.

Любые предложения?

=============

Хорошо, я исследовал дальше. Таким образом, у меня есть OpenEntityManagerInViewFilter с настройками по умолчанию:

Сценарий первый.

[1] MVC контроллер загружает объект пользователя в READONLY транзакции T1 [2] Объект изменен в результате связывания поля MVC [3] второй транзакции работает против таблицы Users в READONLY транзакции Т2. [4] Спящий режим сбрасывает объект, загруженный в T1. [5] Hibernate выдает то запрос

Сценарий 2.

подклассы OEMIVFilter установить FlushMode совершить (по умолчанию автоматически).

Как указано выше, с шагами [4] и [5] отменено, а именно. даже если T2 отмечен как readOnly Hibernate все еще пытается выполнить Flush в конце транзакции. Я мог понять сценарий 1, поскольку readOnly может ссылаться только на текущую транзакцию T2 (и будет пытаться синхронизировать базу данных перед выполнением T2). Однако я ожидал, что в сценарии 2 не будет выпущен флажок.

+0

Подумав об этом немного больше, я полагаю, что имеет смысл, что каждая транзакция привязана к той же сессии спящего режима, а именно: которые связаны с запросом фильтром OEMIV. Это, однако, кажется немного опасным в том, что изменения могут быть сброшены в базу данных без явной перезагрузки и сохранения объекта.OpenSessionViewFilter разрешает указывать singleSession false, который, как мне кажется, относится к проблеме, поскольку каждая транзакция связана с ее собственным сеансом, но я не вижу аналогичного параметра для фильтра OpenEntityManagerInView. –

ответ

2

У меня была такая же проблема в начале. Мы также используем фильтр OSIV, и проблема в нашем случае заключалась в том, что флаг readonly в транзакционной аннотации не был передан в спящий режим. Мы должны были убедиться, что мы используем собственный менеджер транзакций и, что еще важнее, hibernatevendoradapter. Проверьте свою конфигурацию для этого, и если вы не можете решить проблему, отправьте конфигурацию конфигурации настойчивости и пружины.

+0

Привет, Мартин. Я не знаком с HibernateVendorAdapter. Можете ли вы предоставить какую-либо дополнительную информацию о том, как она настроена и что она делает? Благодарю. –

+0

ДА Мартин. Ты прав! Проблема заключалась в том, что я не указал JPAVendorAdaptor для EMF. Без него все оставалось без труда. Самое смешное, что я скопировал исходную конфигурацию JPA из образца проекта, который я создал с помощью Spring Roo. Созданный Roo-файл не указал адаптер, но автоматически настраивает фильтр OEMIV. Поэтому я предполагаю, что кто-либо, загружающий проект с использованием Roo, может испытывать такое же поведение. Любой, спасибо еще раз. Меня смутило. –

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