2015-06-03 2 views
0

Так что есть хранилище Spring JPA:@Transaction поведения весна JPA Repository

@Transactional(readOnly = true) 
public interface UsageReportsRepository extends JpaRepository<UsageReports, Long> { 

@Query(value = "select u from UsageReports u where u.username=:username AND u.requestType='USER_ACTIVITY' ORDER BY u.activityEndTime DESC") 
public List<UsageReports> getLastActiveTime(@Param("username") String username, Pageable pageable); 

} 

и два фильтр, которые используют этот репозиторий.

public class UsageReportingInterceptor implements HandlerInterceptor { 

@Autowired 
private UsageReportsRepository usageReportsRepository; 

@Override 
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
    // Do stuff 
    usageReportsRepository.save(usageReportsBean) 
} 
} 


public class DumpToFile { 

@Autowired 
private UsageReportsRepository usageReportsRepository; 

@Override 
public boolean dumpToFile() throws Exception { 
    // Do stuff 
    List<UsageReports> usageReports = usageReportsRepository.findAll() 
    usageReportsRepository.deleteAll() 
    // Write to file 
} 
} 

Я не чувствую необходимости в сервисном слое, поэтому я вызываю их непосредственно из своих фильтров. Один фильтр вставляет данные, используя этот репозиторий, а другой очищает данные и помещает их в файл. Оба они независимы и могут выполняться в произвольном порядке. Я хочу убедиться, что я не теряю никаких данных в этом процессе. Для этого достаточно аннотации @Transactional? Если нет, что еще мне делать?

+0

Я думаю, что вы неправильно поняли пару вещей - Фильтры и транзакции. Лучший способ проверить, потеряете ли вы данные сейчас? Даже после нескольких запусков? Можете ли вы рассказать нам, почему, по вашему мнению, вы потеряете данные? – prabugp

+0

Например, если есть вызов save() из UsageReportingInterceptor между findAll() и deleteAll() в классе DumptoFile. – n3o

ответ

1

Основываясь на вашем комментарии, я понимаю, что вызов dumpToFile полностью случайный, и это может произойти, так что между вашим findAll и deleteAll было сохранение.

Прежде чем идти дальше, я бы предложил хорошее чтение о том, что такое транзакция и как работает механизм транзакций Spring. Я постараюсь дать краткий обзор, но сейчас это является исчерпывающим. Транзакция - это логическая операция, выполняемая в любой системе. Я говорю логически, потому что одна конкретная транзакция, возможно, придется обновить 2 записи (отслеживание платежей и заказов, если вы хотите придумать пример). И если по какой-то причине какое-либо обновление не удается, другое обновление также должно завершиться неудачно. Вся операция является атомарной, хотя обновлены 2 записи. Таким образом, мы называем эти две операции одной транзакцией.

Существуют и другие параметры [ACID], но одна транзакция должна быть одной логической операцией.

В вашем случае вы полностью пометили свой репозиторий для чтения только для чтения. [Есть несколько типов транзакций, только для чтения позволит вам читать данные, но не изменять их]. Поэтому я не уверен, произойдет ли ваше удаление. Но если вы измените свой конфиг, чтобы разрешить удаление, тогда у нас другая проблема. Проблема блокировки.

Обычно транзакция только для чтения (есть оговорки) блокирует таблицу, из которой вы читаете. Если вы хотите, чтобы ваша таблица была заблокирована, когда вы делаете findAll и deleteAll, вы можете обернуть эти два в одну транзакцию, пометить таблицу как заблокированную (это предотвратит блокировку других запросов до завершения текущей транзакции), do вашей вещи и совершить/откат. Фиксирование/откат освобождает блокировку. Другие запросы продолжают выполняться.

Это всего лишь один из способов сделать это. Другой способ - синхронизировать доступ к репозиторию и заблокировать транзакцию на Java-пути (хотя я бы не рекомендовал его). Могут быть другие способы, но хороший дизайн не должен идеально блокировать всю таблицу по нескольким причинам.

Это не дает вам кода, но я хочу, чтобы вы узнали больше о транзакциях, блокировании таблиц и о альтернативных проектах этого.

+0

Спасибо за ответ. Имеет ли весна какой-либо вариант обертывания двух методов JPA в одну атомную транзакцию? – n3o

+0

Существуют стратегии транзакций, например, можно ли использовать существующую транзакцию или создать новую на разных уровнях. Вы можете просмотреть http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#tx-программирование для информации.Но если вы хотите, чтобы две полностью разные операции были завернуты, вам, возможно, придется вручную управлять своими транзакциями. – prabugp

+0

Да, это то, что я сделал. Это была именно потребность в уровне обслуживания. Создал один и обернул эти два вызова в метод и аннотировал его с помощью @Transaction! – n3o

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