Транзакция в postgresql не зафиксирована, сопоставленные объекты не сохраняются с autoCommit=false

Сопоставленные объекты не сохраняются в БД (Postgresql 8.4) при вызове persist в текущей транзакции. Я использую Spring Transaction Management с

org.springframework.jdbc.datasource.DataSourceTransactionManager

так что все должно быть хорошо. Я установил для режима автоматической фиксации в DataSource значение «false». При установке режима «true» фиксация будет выполнена (и объекты будут сохранены), но это приведет к более серьезным проблемам (например, получение больших двоичных объектов из базы данных). Поэтому я должен установить для режима автоматической фиксации значение "false", что также является предпочтительным режимом, о котором мне все говорили...

Это моя конфигурация постоянства (я сократил код до необходимого):

<bean id="authDatabase" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.postgresql.Driver" />
    <property name="url" value="jdbc:postgresql://localhost:5432/authentication_db" />
    <property name="username" value="test"/>
    <property name="password" value="test"/>
    <property name="defaultAutoCommit" value="false" />               
</bean>

<bean id="serviceInfoSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="authDatabase" />
    <!-- Very important for transactional usage with org.springframework.jdbc.datasource.DataSourceTransactionManager -->
    <property name="useTransactionAwareDataSource" value="true"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
    <property name="annotatedClasses">
        <list>
            <!-- mapped objects, not necessary --->
        </list>
    </property>
</bean>

<!-- defaults to transactionManager -->
<tx:annotation-driven/>

<bean id="authTXManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="authDatabase"/> 
    <qualifier value="auth"/>
</bean>

<!-- more stuff -->

Я также должен упомянуть, что я использую 3 разных менеджера транзакций (конечно, с 3 разными источниками данных)...

Моя собственная аннотация транзакции, которая будет отражена упомянутым выше атрибутом квалификатора:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional("auth")
public @interface AuthenticationTX{}

Аннотированный класс обслуживания, который "должен" сохранять объект...

@AuthenticationTX
@Override
public void loginClient(Client cl) {
    // do stuff
    // call dao.persist(cl);
}

Это журнал при вызове метода службы, который вызывает вызов БД:

16:21:24,031 DEBUG DataSourceTransactionManager:365 - Creating new transaction with name [com.example.ILoginManager.loginClient]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
16:21:24,078 DEBUG DataSourceTransactionManager:205 - Acquired Connection [jdbc:postgresql://localhost:5432/authentication_db, UserName=auth_user, PostgreSQL Native Driver] for JDBC transaction
Hibernate: select user0_.id as id14_, user0_.email as email14_, user0_.firstname as firstname14_, user0_.isLocked as isLocked14_, user0_.lastLogin as lastLogin14_, user0_.lastname as lastname14_, user0_.loginname as loginname14_, user0_.organisation_id as organis10_14_, user0_.passwort as passwort14_, user0_.userGUID as userGUID14_ from UserAccount user0_ where user0_.loginname=?
Hibernate: select client0_.id as id3_, client0_.clientId as clientId3_, client0_.clientType as clientType3_, client0_.connectedAt as connecte4_3_, client0_.language as language3_, client0_.screenHeight as screenHe6_3_, client0_.screenWidth as screenWi7_3_, client0_.securityToken as security8_3_, client0_.user_id as user9_3_ from Client client0_ where client0_.user_id=?
Hibernate: select user0_.id as id14_, user0_.email as email14_, user0_.firstname as firstname14_, user0_.isLocked as isLocked14_, user0_.lastLogin as lastLogin14_, user0_.lastname as lastname14_, user0_.loginname as loginname14_, user0_.organisation_id as organis10_14_, user0_.passwort as passwort14_, user0_.userGUID as userGUID14_ from UserAccount user0_ where user0_.loginname=?
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into Client (clientId, clientType, connectedAt, language, screenHeight, screenWidth, securityToken, user_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: update UserAccount set email=?, firstname=?, isLocked=?, lastLogin=?, lastname=?, loginname=?, organisation_id=?, passwort=?, userGUID=? where id=?
16:21:24,187 DEBUG DataSourceTransactionManager:752 - Initiating transaction commit
16:21:24,187 DEBUG DataSourceTransactionManager:265 - Committing JDBC transaction on Connection [jdbc:postgresql://localhost:5432/authentication_db, UserName=auth_user, PostgreSQL Native Driver]
16:21:24,187 DEBUG DataSourceTransactionManager:323 - Releasing JDBC Connection [jdbc:postgresql://localhost:5432/authentication_db, UserName=auth_user, PostgreSQL Native Driver] after transaction

Как видите, транзакция фиксируется (согласно логу), но ни один объект не сохраняется в бд (хотя выполняется вставка и обновление).

При установке режима фиксации в моей конфигурации источника данных на

имя свойства = «DefaultAutoCommit» значение = «истина»

все работает нормально!

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


person tim.kaufner    schedule 02.09.2010    source источник


Ответы (1)


Для работы с Hibernate вам понадобится HibernateTransactionManager:

<bean id="authTXManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="serviceInfoSessionFactory"/>  
    <qualifier value="auth"/> 
</bean> 
person axtavt    schedule 02.09.2010
comment
Хм, попробую это завтра в офисе. Думал, что я пробовал это уже безуспешно... Вы уверены, что я не могу использовать DataSourceTransactionManager (.jdbc.datasource), который предоставляет Spring? В чем разница между этими двумя менеджерами? - person tim.kaufner; 02.09.2010
comment
@tim: Возможно, мой совет неверен, потому что я не заметил useTransactionAwareDataSource=true. Вам это действительно нужно? - person axtavt; 02.09.2010
comment
Хм, на самом деле я только что прочитал, что мне нужно использовать это свойство при использовании jdbc.datasource.DataSourceTransactionManager. Я изменил менеджер транзакций на тот, который вы упомянули, и это действительно сработало для меня! Вы знаете разницу между этими двумя менеджерами? В журнале говорится (с обоими менеджерами), что операторы отправляются в БД (вставка/обновление) и транзакции фиксируются... Поэтому я понятия не имею, почему подход с jdbc.datasource.DataSourceTransactionManager не работает... - person tim.kaufner; 03.09.2010
comment
@tim: Когда вы используете автономный Hibernate без транзакций Spring, вы фиксируете транзакции с помощью метода commit Hibernate. HibernateTransactionManager делает то же самое для транзакций, управляемых Spring, поэтому Hibernate уведомляется, когда транзакция собирается зафиксироваться, и может выполнять свою работу. useTransactionAwareDataSource=true с DataSourceTransactionManager — это расширенная функция для особых обстоятельств (см. документацию), поэтому я не знаю, почему она не работает. - person axtavt; 03.09.2010
comment
Хорошо, я проведу небольшое исследование. Но в настоящее время это работает для меня, поэтому спасибо за объяснение и вашу помощь. - person tim.kaufner; 03.09.2010