Должен ли я поместить аннотацию @Transactional для подметодов также весной?

У меня есть основной метод обработчика БД, который вызывает другие методы, которые также работают с вещами BD.

Я поставил аннотацию @Transactional для основного метода, потому что хочу все откатить, если что-то пойдет не так.

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

Например, в методе удаления возникает исключение, как сделать так, чтобы записывающая часть тоже откатилась:

@Transactional
public void maintDbTings() {
    writing();
    deleting();
}

@Transactional //do I need this?
public void writing() {
    //no exceptions
}

@Transactional //do I need this?
public void deleting() {
    //exception occurs
}

person victorio    schedule 07.03.2017    source источник
comment
Поскольку они общедоступны и могут вызываться сами по себе, я полагаю, вам нужна аннотация. Просто убедитесь, что они не создают свои собственные транзакции без необходимости, и используйте транзакцию mainDbThings, если это возможно.   -  person M. Prokhorov    schedule 07.03.2017
comment
а если бы они были приватными и вызывались только из основного метода? будет ли метод записи откатываться, если метод удаления имеет исключения?   -  person victorio    schedule 07.03.2017
comment
Чтобы уточнить, вам это не нужно, если методы вызываются из mainDbTings, так как mainDbTings уже запускает транзакцию, если она есть. Но тогда эти методы должны быть приватными. Если их можно вызывать, минуя mainDbTings, и они должны быть транзакционными, то они также должны быть аннотированы.   -  person JB Nizet    schedule 07.03.2017


Ответы (3)


Spring начинает транзакцию, когда встречает метод с аннотацией @Transactional. Область действия транзакции охватывает выполнение этого метода, выполнение любых методов, вызываемых этим методом, и так далее, пока метод не вернется. Любые управляемые ресурсы, на которые распространяется настроенный PlatformTransactionManager и которые вы используете во время области транзакции, участвуют в транзакции. Например, если вы используете org.springframework.jdbc.datasource.DataSourceTransactionManager, соединение, полученное из связанного DataSource, автоматически участвует в транзакции. Транзакция завершается одним из двух способов: либо метод завершает выполнение напрямую, и диспетчер транзакций фиксирует транзакцию, либо метод генерирует исключение, и диспетчер транзакций откатывает транзакцию.

Надеюсь теперь понятно.

person Faraz    schedule 07.03.2017

Проще говоря, когда у вас есть это:

@Transactional
public void maintDbTings() {
    writing();
}


@Transactional //do I need this?
public void writing() {
    //no exceptions
}

И вызовите mainDbTings, @Transactional на writing не действует. Это означает, что транзакция, которая была начата для mainDbThings, все еще будет присутствовать/открыта в письменной форме. Так что в этом случае вы можете легко отказаться от него.

С другой стороны, поскольку writing является общедоступным, кто-то может назвать его ожидающим, что он будет транзакционным, поскольку, скорее всего, это класс обслуживания. В этом случае преобразование writing в @Transactional является обязательным, и вы не можете его отбросить.

Так что это действительно ваши потребности.

person Eugene    schedule 07.03.2017
comment
Также можно использовать свойство propagation для изменения транзакции для вложенных вызовов. docs.spring. io/spring-framework/docs/current/javadoc-api/org/ - person Vimal Bera; 07.03.2017

Вы можете использовать свойства распространения, такие как REQUIRED, REQUIRES_NEW, NESTED, в соответствии с вашими требованиями, как описано в приведенной ниже ссылке:

http://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html

person KayV    schedule 07.03.2017