Як використовувати @Transactional із Spring Data?


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 ми маємо цю анотацію щодо класу реалізації, що підтримує проксі ( 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/

З найкращими побажаннями


2

Вам слід використовувати @Repositoryанотацію

Це пов’язано з тим @Repository, що використовується для перекладу вашого неперевіреного винятку SQL у Spring Excpetion, і єдиним винятком, який вам слід мати, єDataAccessException


10
Загалом це вірно при використанні Spring, але оскільки сховища Spring Data вже підтримуються проксі-сервером Spring - використання @Repository не має ніякої різниці.
Aleksander Blomskøld

0

Ми також використовуємо анотацію @Transactional, щоб заблокувати запис, щоб інший потік / запит не змінив прочитане.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.