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

Я только начал работать над проектом 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);
}

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


person Byron Voorbach    schedule 01.05.2012    source источник


Ответы (4)


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

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

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

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

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

person Oliver Drotbohm    schedule 05.05.2012
comment
Итак, вкратце: я должен использовать @Transactional для запросов добавления/редактирования/удаления и @Transaction(readOnly = true) для запросов выбора во всех моих DAO-методах? - person Byron Voorbach; 06.05.2012
comment
Точно. Самый простой способ сделать это — использовать @Transactional(readOnly = true) в интерфейсе (поскольку он обычно содержит в основном методы поиска) и переопределить этот параметр для каждого модифицирующего метода запроса с помощью простого @Transactional. Собственно так это и сделано в SimpleJpaRepositoy. - person Oliver Drotbohm; 06.05.2012
comment
@Oliver, спасибо за исчерпывающее объяснение. html#listing8" rel="nofollow noreferrer">ibm.com/developerworks/java/library/j-ts1/index.html#listing8› . В нем говорится: Суть в том, что когда вы используете инфраструктуру на основе ORM, флаг только для чтения совершенно бесполезен и в большинстве случаев игнорируется. Но если вы все еще настаиваете на его использовании, всегда устанавливайте режим распространения в SUPPORTS.. После прочтения этого я не уверен, следует ли мне использовать (readOnly = true) в одиночку.. должен ли он использоваться всегда с режимом распространения как SUPPORTS. - person Anupam Gupta; 05.05.2013
comment
Почти все неправильно в этом разделе статьи. Указав, что вы не пишете, управляемый JDBC может (улучшит) улучшить производительность для взаимодействий с БД. Он также может обнаруживать и отклонять случайно выпущенные записи. Вдобавок ко всему, Spring отключает сброс JPA/Hibernate в режиме только для чтения, что может сильно повлиять на производительность, если вы читаете графы больших объектов, поскольку тогда провайдеру не нужно выполнять грязные проверки. Хотя флаг может не иметь большого влияния на саму транзакцию, но это далеко не все, что нужно учитывать. - person Oliver Drotbohm; 07.05.2013
comment
Я могу поручиться за улучшение производительности в случае графов больших объектов или вариантов использования, загружающих большое количество управляемых объектов. - person Shailendra; 16.02.2015
comment
Не читал статью, но нужно спросить, зачем вообще использовать транзакцию, если все, что я планирую сделать, это SELECT? Я думаю, что это, вероятно, то, что пытается описать связанная статья. Нет такого пункта. Распространение SUPPORTS будет использовать текущую выполняющуюся транзакцию, если таковая существует, в противном случае не создавать ее. Это ключ. Только операции сохранения и удаления требуют транзакции. Итак, В ЧЁМ смысл иметь транзакцию только для чтения? Лучше вообще не использовать. - person Martin Andersson; 14.07.2019
comment
@MartinAndersson отмечает, что любое обращение к базе данных выполняется в транзакции. Посмотрите здесь хорошее объяснение и что-то еще, чтобы узнать: stackoverflow.com/questions/13539213/ - person Lubo; 09.02.2020
comment
Чтобы узнать больше о некоторых оптимизациях в спящем режиме о readOnly = true, вы можете взглянуть на vladmihalcea.com/ - person Lubo; 09.02.2020

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

С уважением

person dgiffone    schedule 06.05.2012

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

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

person danny.lesnik    schedule 01.05.2012
comment
В целом это верно при использовании Spring, но поскольку репозитории Spring Data уже поддерживаются прокси-сервером Spring, использование @Repository не имеет никакого значения. - person Aleksander Blomskøld; 06.05.2012

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

person Zozo    schedule 15.01.2020