Статьи

Пример декларативных операций Spring

Транзакция — это единица работы, которая имеет свойства ACID (атомарные, согласованные, изолированные и долговечные). Атомное означает, что все изменения происходят или ничего не происходит. Если деньги списываются со счета и зачисляются на другой счет, транзакция гарантирует, что дебет и кредит завершены или не завершены. Согласованный подразумевает, что изменения оставляют данные в согласованном состоянии. Изолированный подразумевает, что изменения не мешают другим изменениям. Долговременность подразумевает, что после внесения изменений они остаются зафиксированными

Менеджеры ресурсов, такие как реляционные базы данных, предоставляют менеджер транзакций и API для управления транзакциями. Те, кто знаком с JDBC, знают, что по умолчанию транзакция запускается из-за параметра autocommit = true. Каждый оператор, который изменяет базу данных, автоматически фиксируется. Это поведение можно изменить, установив autocommit в false. Теперь программист должен явно начать транзакцию, а затем зафиксировать или откатить транзакцию.

Транзакции, которые имеют дело только с одним ресурсом, таким как одна база данных, называются локальными транзакциями. Транзакции, которые охватывают несколько ресурсов, таких как несколько баз данных или база данных и механизм обмена сообщениями, называются глобальными транзакциями. Глобальные транзакции реализуются с использованием протокола XA, который включает в себя двухфазную фиксацию. Спецификация JTA описывает Java API для программистов для работы с глобальными транзакциями. Методы транзакций в JDBC, такие как begin, commit, rollback, работают только с JDBC и реляционными базами данных, где JTA может работать с любым транзакционным ресурсом.

Однако код, используемый для работы с транзакциями, представляет собой код платформы, который может обрабатываться средой. В начале метода вам нужно начать транзакцию, а когда метод завершится, вам нужно либо зафиксировать, либо откатить транзакцию. Если вы работали с EJB, вам может быть известно, что вы можете указать в дескрипторе развертывания транзакционную среду, в которой должен выполняться метод. Например, вы можете сказать «Требуется новый», что означает начать новую транзакцию перед вызовом метода. Контейнер начинает новую транзакцию до вызова метода и фиксирует ее, когда метод возвращается. Программисту не нужно писать какой-либо Java-код для обработки транзакции.

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

Для этого урока вам понадобятся:

(1) Весна 3.0
(2) Затмение не является обязательным. Я использую затмение в качестве моей IDE. Eclipse позволяет вам экспортировать войну, которую можно развернуть в Tomcat. Но вы также можете использовать другие IDE или инструменты командной строки.
(3) Вы можете скачать исходный код для этого примера по адресу springjdbcwithTransaction.zip .

Мы повторно используем пример из JDBC с блогом Spring, который мы написали некоторое время назад. Давайте добавим поддержку транзакций в MemberSpringJDBCDAO. Этот класс имеет метод insertMember, который вставляет член в базу данных. Давайте немного изменим метод, чтобы выбрасывать RuntimeException после вставки в базу данных. Добавлено исключение времени выполнения, чтобы сделать вид, что произошла ошибка в бизнес-логике при обновлении базы данных.

01
02
03
04
05
06
07
08
09
10
11
public int insertMember(Member member) {
    JdbcTemplate jt = getJdbcTemplate() ;
    Object[] params = new Object[{member.getFirstname(),
        member.getLastname(),
        member.getStreet(),member.getCity(),
        member.getZip(),member.getEmail(),member.getPassword()} ;
   
    int ret = jt.update(insert_sql, params) ;
    throw new RuntimeException("simulate Error condition') ;
    return ret ;
}

В этом методе вы ожидаете, что вставка будет зафиксирована в базе данных? Ответ Да, хотя это не желательное поведение. Поведение JDBC по умолчанию — autocommit = true, что означает, что каждая вставка или обновление фиксируются немедленно. Вы можете установить autocommit = false и явно зафиксировать или откатить в конце метода. Но намного легче позволить вашему контейнеру справиться с этим.

Чтобы добавить декларативное управление транзакциями к вышеуказанному методу, выполните следующие действия:

Шаг 1. Определите менеджер транзакций в springjdbcdao.xml

1
2
<bean id="txManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"/>

Spring работает с менеджером транзакций для начала и завершения транзакций.

Шаг 2. Включите поддержку аннотаций транзакций.

Добавить в springjdbcdao.xml

1
<tx:annotation-driven transaction-manager="txManager"/>

Шаг 3. Добавьте аннотацию @Transactional в метод insertMember.

1
2
3
@Transactional
public int insertMember(Member member) {
...

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

Распространение: обязательно

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

Уровень изоляции: по умолчанию

Используйте уровень изоляции по умолчанию для основного менеджера ресурсов.

Откат: Любое исключение во время выполнения вызывает откат

Шаг 4. Запустите обновленный метод insertMember, используя тест Junit MemberSpringJDBCDAOTest.

Вы увидите следующие журналы от менеджера транзакций, указывающие на откат транзакции.

org.springframework.jdbc.datasource.DataSourceTransactionManager — Инициирование отката транзакции
2501 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager — Инициирование отката транзакции
2501 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager — откат транзакции JDBC для соединения [org.apache.derby.impl.jdbc.EmbedConnection40@13320911 (XID = 2827), (SESSIONID = 1), (DAT c: \ manoj \ mjprojects \ database \ pumausers), (DRDAID = null)] 2501 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager — откат транзакции JDBC для соединения [org.apache.derby.impl.jdbc. EmbedConnection40 @ 13320911 (XID = 2827), (SESSIONID = 1), (DATABASE = c: \ manoj \ mjprojects \ database \ pumausers), (DRDAID = null)] 2511

Используйте SQL для проверки таблицы базы данных. Убедитесь, что запись не добавлена.

Шаг 5: Удалите исключение runtimeexception из метода insertMember и снова запустите тест.

Журнал отладки Spring показывает, что транзакция зафиксирована. Используйте SQL для проверки таблицы базы данных. Убедитесь, что запись добавлена ​​в таблицу.

Таким образом, транзакции необходимы для поддержки свойств ACID для источников данных. Декларативные транзакции с использованием Spring облегчают эту задачу.

Ссылка: Весенние и декларативные сделки от нашего партнера JCG Маноя в отчете Хангаонкар .

Статьи по Теме :