简体   繁体   中英

spring Transaction management not working

I was using programmatic transaction management in spring, now I have switched to declarative transaction management.

SessionFactory

<beans:bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="packagesToScan" value="com.hcentive.cig.domain" />
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
                </beans:prop>
                <beans:prop key="hibernate.show_sql">true</beans:prop>
                <beans:prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean> 

TransactionManager

<beans:bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory">
            <beans:ref bean="sessionFactory" />
        </beans:property>
    </beans:bean>

Now If run my code

@Override
    @Transactional
    public Request saveRequest(Request request) {
        sessionFactory.getCurrentSession().save(request);
        return request;
    }

I get exception save is not valid without an active transaction

if I remove below line

<beans:prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</beans:prop>

I get

No CurrentSessionContext configured!

You definitely don't need this setting:

<beans:prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</beans:prop>

Spring Transaction Management layer should bind the Hibernate Session to the current running Thread.

The settings are fine, the only thing that might cause it comes from this statement of yours:

no it is getting called from service layer , and also I have tried moving @ transactional to service layer

You need to expose this method:

Request saveRequest(Request request);

through a Service interface, that you inject in any other component (web or other service layer beans).

To validate this, you can place a debug break-point in the saveRequest method implementation, and look for the TransactionInterceptor up the call-stack. If it's not there, then Spring couldn't wrap your method call into a Transaction Aspect processing logic.

For @Transactional to be effective you have to tell the Spring context that you want to use that. Annotations without a processor for that annotation is pretty useless. To enable the processor for the @Transactional annotation add <tx:annotation-driven /> to your context. (As explained here in the reference guide).

Your hibernate configuration is also problematic when using Spring you shouldn't mess around with the hibernate.current_session_context_class configuration property (unless you use some specific JTA provider but apparently you aren't). If you start setting that property you will break proper spring integration for transaction management. Spring already sets that property for you and your setting overrides the default.

Your configuration should look something like this.

<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <beans:property name="dataSource" ref="dataSource" />
    <beans:property name="packagesToScan" value="com.hcentive.cig.domain" />
    <beans:property name="hibernateProperties">
        <beans:props>
            <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
            <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</beans:prop>
            <beans:prop key="hibernate.show_sql">true</beans:prop>
        </beans:props>
    </beans:property>
</beans:bean>   

<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref bean="sessionFactory" />
</beans:bean>

<tx:annotation-driven />

Having your function annotated as Transactional is not necessarily enough. You also need to ensure that:

  • Your bean gets created via Spring (defined as @Component and found via componentScan OR declared in xml configuration)
  • The reference to your bean needs to be obtained through Spring dependency injection

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM