2014-12-30 2 views
0

Недавно я работал с Spring boot + spring data jpa + hibernate. Я столкнулся с одной проблемой с весенними транзакциями. Вот мой класс обслуживания и два вопроса:Весенние транзакции с ловушками Исключения

@Transactional 
@Service 
class MyService { 

    @Autowired 
    private MyRepository myRep; 

    public void method_A() { 
     try { 
      method_C(); 

      ..... 

      method_B(); 
     } catch(Exception e) {} 
    } 

    public void method_B() { 
     Entity e = new Entity(); 
     e.set(...); 

     myRep.save(e); 
    } 

    public void method_C() throws Exception { 
     .... 
    } 
} 

1.Если метод method_C() генерирует исключение, и я хочу, чтобы поймать его и зарегистрировать ее, транзакция не rollbacked в методе method_B(), поскольку исключение не доходит до весны фреймворк. Итак, как мне сделать, чтобы поймать Исключения из method_C() и в то же время не потерять способность метода method_B() откат?

2. Рассмотрите новый метод method_A().

public void method_A() { 
    for(...) { 
     ... 
     ... 
     method_B(); 
    } 
} 

Я хочу, чтобы вызвать method_B() в цикле. Если возникает исключение в method_B(), я хочу, чтобы транзакция method_B() была отклонена, но method_A() не должен выйти, и цикл должен продолжаться. Как я могу это достичь?

+0

Не перехватывайте исключения, пружина будет регистрировать исключение в любом случае, включая полную трассировку стека, поэтому зачем беспокоиться об этом самостоятельно. Для варианта 2 просто установите try/catch внутри цикла for. Метод B по-прежнему действует как есть (включая откат), и метод все еще продолжается. Если вам нужна дополнительная обработка исключений, вы всегда можете написать аспект после броска, чтобы выполнить регистрацию, или добавить улов, но всегда восстанавливать исключение (но из-за уже зарегистрированного Spring, который был бы избыточным). –

+0

Если я добавлю блок try-catch в цикле, транзакция не будет отменена в 'method_B ​​()'. Объект сохраняется и заносится в базу данных. – polis

+0

Предполагалось, что метод A не был в транзакции, только метод B. –

ответ

1

Я решил свои 2 проблемы таким образом: создал еще один класс @Service и переместил method_B() в него. Я аннотировал этот класс как @Transactional. Теперь метод method_A() выглядит следующим образом:

public void method_A() { 
    for(...) { 
     ... 
     try { 
     anotherService.method_B(); 
     } catch (Exception e) { 
     logger.error(...); 
     } 
    } 
} 

Если RuntimeException происходит в методе method_B(), исключение propertly регистрируется, сделка method_B() является rollbacked и цикл непрерывно. Спасибо всем за ответы.

0

Вместо исключения исключений выполните следующие действия. (код ошибки возврата).

Обновление: Я прочитал ваш вопрос после публикации. если вы вызываете метод method_b из метода_A, оба находятся под одной транзакцией. К сожалению, вы не можете откатить только изменения method_b. Spring считает это одной транзакцией, если все они находятся под одним классом обслуживания. (все методы).

Одна вещь, которую вы можете попробовать, это следующее.

request to--> Controller() ---> (spring opens transaction) service_method_a(); (spring closes transaction) 
       Controller() ---> (spring opens transaction) service_method_c(); (spring closes transaction) 
       Controller() ---> (spring opens transaction) service_method_b(); (spring closes transaction) 
return <-- 

Я надеюсь, что это имеет смысл

Каждый из ваших методов а, б, бросать исключения, если он любит быть rolledback.

Обновление: другой подход. Это намного лучше.

Если каждый из вашего метода в другой услуги, то вы можете использовать следующие аннотации пружины для запуска каждого из метода в различных границах транзакций

p v serviceA{ 

    @transactional 
    method_a(){ 
     serviceb.method_b(); 
    } 

} 

p v serviceB{ 

    @Transactional(propagation=Propagation.REQUIRED) 
    method_b(){ 

    } 

} 

больше на ней here

Весенняя транзакционная история here. Прочтите пункты, приведенные ниже этой статьи. Это наиболее важно при разработке весеннего транзакционного приложения.

+0

Зевс, спасибо за ваш ответ, но 'method_B ​​()' не будет откат в случае Exception, потому что вы окружили его тело блоком try-catch. – polis

+0

@polis обновил мой ответ – Zeus

+0

стоит попробовать, спасибо. Кроме того, я хочу спросить об этом ваш оператор: «если вы вызываете метод method_b из метода_A, оба находятся под одной транзакцией. К сожалению, вы не можете откатить только изменения method_b. Spring считает это одной транзакцией, если все они находятся под одним классом обслуживания». Если эти методы находятся под одной и той же транзакцией, почему мы можем добавить аннотацию @ @ Transactional до метода (а не класса) с разными параметрами (распространение, изоляция и т. Д.)? Это потому, что мы хотим, чтобы транзакция в разных методах вела себя по-другому? – polis

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