Автоматическое управление транзакциями Hibernate с помощью Spring?

Как далеко зашла инфраструктура Spring в обработке транзакций? Мое чтение книги «Spring In Action» с ее примерами предполагает, что вы создаете методы DAO, которые не беспокоятся об управлении сеансами и транзакциями, просто настроив фабрику сеансов и шаблон транзакций в XML, а затем подключив их к вашему DAO. Документация SpringSource.org, с другой стороны, предполагает, что для этого нужны тонны XML и/или аннотаций.

В чем тут правда, как проще всего взять код по строкам

get session from sessionfactory
open transaction
preform database actions
commit transaction with error handling

и сделать это просто

preform database actions

свести к минимуму объем шаблонного транзакционного кода, который я использую в своих методах?


person James McMahon    schedule 16.04.2009    source источник


Ответы (2)


Spring предоставляет как минимум 3 способа разграничения транзакций:

1) Программная обработка через TransactionTemplate или PlatformTransactionManager - легкая конфигурация, но агрессивная

2) Декларативный через XML - подробный XML, но неинвазивный

3) Декларативный через аннотации - легкий в XML, не инвазивный

Какой из них вы выберете, зависит от того, какой из них лучше всего соответствует вашим потребностям, Spring не делает этот выбор за вас. Судя по вашему вопросу, похоже, что подход к аннотации - это то, что вам нужно.

Я предлагаю прочитать справочное руководство Spring, раздел обработки транзакций на основе аннотаций. Это ясно и лаконично.

Я всегда сначала обращаюсь к справочным документам и только к книге, если ее нет в документах.

person skaffman    schedule 17.04.2009

Есть некоторая работа, которую вы должны сделать, чтобы иметь возможность делать именно это, но ее совсем немного. Предположительно, вы будете использовать JPA с выбором собственного провайдера, например. Спящий режим. Затем вам нужно поместить файл persistence.xml, определяющий блок сохраняемости, в папку META-INF:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" 
             version="1.0">
    <persistence-unit name="YourDatabasePersistenceUnitName" transaction-type="RESOURCE_LOCAL"/>           
</persistence>

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

<bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>/WEB-INF/jdbc.properties</value>     
        </property>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
          destroy-method="close" scope="singleton">
        <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="YourDatabasePersistenceUnitName"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="POSTGRESQL" />
                <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect"/>
                <property name="showSql" value="true"/>
                <property name="generateDdl" value="false"/>
            </bean>
        </property>     
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

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

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

 <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

Некоторые свойства выше могут быть изменены или добавлены в зависимости от ваших потребностей. Пример для JPA с базой данных Hibernate и PostgreSQL, как вы уже догадались.

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

@Repository
@Transactional
public class UserJpaDAO {

    protected EntityManager entityManager;

    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public void save(User theUser) {
        entityManager.persist(theUser);
    }

    public User update(User theUser) {
        return entityManager.merge(theUser);
    }
 }

где Пользователь — это объект JPA, определенный вашим приложением. Вы можете управлять транзакциями на уровне менеджера/контроллера, который вызывает ваши DAO — на самом деле я так и делаю — но я поместил их здесь, чтобы не слишком загромождать пример.

Хорошие ссылки, к которым вы можете перейти прямо вместо моих примеров: http://icoloma.blogspot.com/2006/11/jpa-and-spring-fucking-cooltm_26.html 3 верхних ссылки, на которые он ссылается, также стоит посетить.

person topchef    schedule 16.04.2009
comment
Спасибо за ответ, завтра на работе поиграюсь. Однако обе ваши ссылки в конце одинаковы. - person James McMahon; 17.04.2009
comment
извините, но ссылка, которую я предоставил, содержит еще 3 ссылки, включая другую, которую я имел в виду... - person topchef; 17.04.2009
comment
Порядок xml не должен быть важен, кроме очевидных зависимостей между bean-компонентами. - person topchef; 18.04.2009
comment
сообщение в блоге кажется мертвым. Можете ли вы порекомендовать другой пост? - person Durja; 04.01.2019