Как использовать @Transactional с данными Spring?

82

Я только начал работать над проектом Spring-data, Hibernate, MySQL, JPA. Я перешел на spring-data, чтобы не беспокоиться о создании запросов вручную.

Я заметил, что использование @Transactionalне требуется, когда вы используете spring-data, поскольку я также пробовал свои запросы без аннотации.

Есть ли конкретная причина, по которой я должен / не должен использовать @Transactionalаннотацию?

Работает:

@Transactional
public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

Также работает:

public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

Заранее спасибо!

Байрон Ворбах
источник

Ответы:

141

О чем на самом деле ваш вопрос? Использование @Repositoryаннотации или @Transactional.

@Repositoryне требуется вообще, поскольку объявляемый вами интерфейс будет поддерживаться прокси-сервером, который инфраструктура Spring Data создает и в любом случае активирует преобразование исключений. Таким образом, использование этой аннотации в интерфейсе репозитория Spring Data вообще не имеет никакого эффекта.

@Transactional- для модуля JPA у нас есть эта аннотация класса реализации, поддерживающего proxy ( SimpleJpaRepository). Это происходит по двум причинам: во-первых, для сохранения и удаления объектов требуется транзакция в JPA. Таким образом, нам нужно убедиться, что транзакция выполняется, что мы делаем, аннотируя метод с помощью@Transactional .

Чтение методов , как findAll()и findOne(…)использует @Transactional(readOnly = true), не является строго необходимым , но вызывает несколько оптимизаций в инфраструктуре транзакции (установив FlushModeдля MANUALпозволить живучести поставщиков потенциально пропустить грязные проверки при закрытии EntityManager). Кроме того, установлен флаг и для соединения JDBC, что вызывает дальнейшую оптимизацию на этом уровне.

В зависимости от того, какую базу данных вы используете, он может опускать блокировки таблиц или даже отклонять операции записи, которые вы могли вызвать случайно. Таким образом, мы рекомендуем также использовать @Transactional(readOnly = true)для запросов методы, которые вы можете легко добиться, добавив эту аннотацию в интерфейс репозитория. Убедитесь, что вы добавили равнину @Transactionalк методам управления, которые вы могли объявить или изменить в этом интерфейсе.

Оливер Дротбом
источник
9
Вкратце: я должен использовать @Transactional для запросов на добавление / редактирование / удаление и @Transaction (readOnly = true) для выборочных запросов во всех моих DAO-методах?
Байрон Ворбах
21
Точно. Самый простой способ сделать это - использовать @Transactional(readOnly = true)в интерфейсе (поскольку он обычно содержит в основном методы поиска) и переопределить этот параметр для каждого метода изменения запроса с помощью простого @Transactional. На самом деле так это и делается SimpleJpaRepositoy.
Оливер Дротбом
@Oliver, спасибо за исчерпывающее объяснение .. Но пока просматриваю другую ссылку [транзакция-яма-водопад] < ibm.com/developerworks/java/library/j-ts1/index.html#listing8 >. В нем говорится: « Суть в том, что при использовании инфраструктуры на основе ORM флаг только для чтения совершенно бесполезен и в большинстве случаев игнорируется. Но если вы все еще настаиваете на его использовании, всегда устанавливайте режим распространения на ПОДДЕРЖКУ » . .После прочтения я не уверен, должен ли я использовать только (readOnly = true) .. должен ли он всегда использоваться с режимом распространения в качестве ПОДДЕРЖКИ.
Анупам Гупта
9
В этом разделе статьи почти все не так. Указывая, что вы не пишете, управляемый JDBC может (улучшит) производительность взаимодействия с БД. Он также может обнаруживать и отклонять случайно выполненные записи. Вдобавок к этому Spring отключает очистку JPA / Hibernate в режиме только для чтения, что может сильно повлиять на производительность, если вы читаете графы больших объектов, поскольку тогда провайдеру не нужно выполнять грязные проверки на нем. Флаг может не иметь большого влияния на саму транзакцию, но это далеко не все, что нужно учитывать.
Оливер Дротбом
Я могу поручиться за повышение производительности в случае больших графов объектов или сценариев использования, загружающих большое количество управляемых объектов.
Шайлендра
3

Я думаю, что вопрос немного шире и не может быть сокращен по аннотациям на уровне доступа к данным. Нам нужно рассмотреть весь стек приложения, стратегии транзакций, которые мы хотим применить, и так далее. На сайте IBM developerworks есть очень исчерпывающий набор статей по этой теме Марка Ричардса. Вы можете найти первый здесь: https://developer.ibm.com/articles/j-ts1/

С уважением

dgiffone
источник
2

Вы должны использовать @Repositoryаннотацию

Это связано с тем, что @Repositoryон используется для перевода вашего непроверенного исключения SQL в Spring Excpetion, и единственное исключение, с которым вы должны работать, этоDataAccessException

danny.lesnik
источник
10
В целом это верно при использовании Spring, но поскольку репозитории Spring Data уже поддерживаются прокси-сервером Spring, использование @Repository не имеет никакого значения.
Александр Бломскельд,
0

Мы также используем аннотацию @Transactional для блокировки записи, чтобы другой поток / запрос не изменил чтение.

Зозо
источник