Search code examples
javaspringtransactionsspring-aopspring-annotations

Why does not "@Transactional(propagation = propagation.NEVER)" work?


In the Spring docs, for NEVER propagation:

Execute non-transactionally, throw an exception if a transaction exists.

I wanted to try like following:

@Transactional(propagation = Propagation.NEVER)
public void getDeps(long ID) {
    System.out.println(databaseImp.getDepartmentByID(ID));
}

@Transactional(propagation = Propagation.REQUIRED)
public void allProcessOnDB_second(long ID) {
    getDeps(ID);
    operation(ID);
}

@Transactional
public void operation(long id){
    System.out.println(databaseImp.getDepartmentByID(id));
}

Well, it is not important what code wants to do.
I use the @Transactional(propagation = Propagation.NEVER) and I use this method in any transactional method but it doesn't work. I mean it must throw an exception, but it doesn't.

My Spring meta configuration file (XML) contains the following:

<context:annotation-config></context:annotation-config>
<context:component-scan base-package="database.transactionmanagement"/>

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

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg name="dataSource" ref="datasource2"/>
</bean>

<bean id="datasource2" class="org.apache.tomcat.dbcp.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost/hr"/>
    <property name="username" value="root"/>
    <property name="password" value=""/>
</bean>

Thanks for your answers.


Solution

  • @Transactional annotations only apply to the Spring proxy objects. For example, if you call allProcessOnDB_second() from some spring bean which injects your service like this

    @Autowired 
    private MyService myService; 
    ...
    myService.allProcessOnDB_second();
    

    then myService is Spring proxy, and its @Transactional(propagation = Propagation.REQUIRED) is applied. If you were to call myService.getDeps(id) then @Transactional(propagation = Propagation.NEVER) would be applied.

    But when you call the first method, and then second method from it, then second method isn't called through Spring proxy but rather directly, so its transactional configuration is ignored.