jerryscott2014 opened SPR-12564 and commented

Hi, spring team. 1. when integration with mybatis (with mybatis-spring), it seems that the transaction does not make any sense which I could leave any use message.

  1. From the reference URL,it might be the spring transaction should do some improvement. 2.1 My configuration: 2.1 I have some appContext (like parent and sub context), the parent context(suppose it to be "appContext_channel.xml")is like this (others omitted
<import resource="appContext_dao.xml" />

<!--enable annotation support --><context:annotation-config />

<!--enable mbean export -->
<context:mbean-export />
2.2  the appContext_dao.xml  like this:
   <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
        init-method="init" destroy-method="close">
   </bean>

  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="plugins">
            <list>
                <ref bean="pageQueryInterceptor" />
                <ref bean="optimistLockInterceptor" />
            </list>
        </property>
        <!-- 引入mapper资源文件 -->
        <property name="mapperLocations" value="${DEFAULT_MAPPER_LOCATION}"></property>
    </bean>

    <!--构造sqlSessionTemplate(支持批量) -->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory" />
        <constructor-arg index="1" value="BATCH" />
    </bean>

    <!-- 引入支持jdbc的事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 引入jta的关联支持(userTransactionManager以及userTransaction) -->
    <bean id="userTransManager" class="com.zjht.channel.server.tx.xa.JtaTransManagerHelper"
        factory-method="createUserTransactionManager" init-method="init"
        destroy-method="close">
        <constructor-arg value="${DEFAULT_JTA_STARUP_SERVICE}" />
        <constructor-arg value="${DEFAULT_JTA_FORCE_SHUTDOWN}" />
    </bean>

    <bean id="userTransaction" class="com.zjht.channel.server.tx.xa.JtaTransManagerHelper"
        factory-method="createUserTransaction">
        <constructor-arg value="${DEFAULT_JTA_TRANS_TIMEOUT}" />
    </bean>

    <!-- 缺省jta事务管理器(由应用引用决定) -->
    <bean id="jtaTransactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <constructor-arg ref="userTransaction" />
        <constructor-arg ref="userTransManager" />
    </bean>

    <!-- 引入annotation方式的事务注解 (针对jdbc|jta方式) -->
    <tx:annotation-driven transaction-manager="transactionManager"
        mode="aspectj" />

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

    <!-- 引入aspectj行为 -->
    <aop:aspectj-autoproxy proxy-target-class="true" />

2.3. then I use com class as the @Configuration defined to start the appContext_channel like this:

@ImportResource({ "classpath:appContext_channel.xml" })
@EnableReactor
@MapperScan(basePackages = { "com.zjht.channel.platform.mapper" })
@ComponentScan(basePackages = { "com.zjht.channel.platform.service" })
@Configuration
@Import({ ChannelEnvConfiguration.class })
public class ChannelPlatformConfiguration {
   //omitted
}
  1. from 2.3. the configuration or main class is located in package "com.zjht.channel.platform.service"". and it would call the component-scan annotation to complete the reference under such package. but to my surprise, the transaction does not bind the spring transaction itself. while tracing the code to DataSourceUtils.isConnectionTransactional() such method called and returned false. so the mybatis spring transaction bind process is fail like this:
2014-12-22 11:37:59.810 DEBUG [main] o.m.s.SqlSessionUtils [SqlSessionUtils.java:104] Creating a new SqlSession
2014-12-22 11:37:59.857 DEBUG [main] o.m.s.SqlSessionUtils [SqlSessionUtils.java:140] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1e3e097] was not registered for synchronization because synchronization is not active
2014-12-22 11:38:00.185 DEBUG [main] c.z.c.p.m.ChannelAppServiceMapper [LoggingCache.java:62] Cache Hit Ratio [com.zjht.channel.platform.mapper.ChannelAppServiceMapper]: 0.0
2014-12-22 11:38:00.248 DEBUG [main] o.m.s.t.SpringManagedTransaction [SpringManagedTransaction.java:86] JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1aa85ab] will not be managed by Spring
  1. conclusion: 4.1 I use AnnotationConfigApplicationContext with the configuration class(listed above) to start the appContext (the subContext defined the transaction support)--- with enabled

4.2 the class with @Configuration also use the @ComponentScan to scan the annotation under the package to complete the bean initialization

4.3 I use the @Transactional("transactionManager") marked in the service for mapper(the mybatis mapper interface) calling like this: {``java@Service@Transactional("transactionManager") public class ChannelAppServiceCfgCreateImpl extends DefaultChannelAppServiceCfgCreateImpl {@Autowired` private ChannelAppConfigMapper channelAppConfigMapper;

@Autowired private ChannelAppServiceMapper channelAppServiceMapper;

@Autowired private ChannelTerminalServiceMapper channelTerminalServiceMapper;

   //omitted

}


after the calling completed, the debug log showed that the transaction of spring was not active. 

5. suggestion:
    5.1 the way to start appContext listed above is very common with parent appContext (with resources import )and sub-appContext (like mvc or dao configuration) 

    5.2  could spring provide further support for transaction (with annotation enhancement)  for those bean with `@Service` or `@Controller` under componet-scan enabled.  we found it was hard to locate where the problem just like why the transaction does not effect for the configuration listed like  `<tx:annotation-driven />` has been marked. but in fact I could not 
make the service around transaction.

so would spring team add such for enhancement ,once those marked with @Transactional  as the sub-appContext defined and with component-scan, spring should make sure of the calling around the service should be under transaction.

Reference URL: http://jinnianshilongnian.iteye.com/blog/1850432

Attachments: - channelserver.log (1.56 kB) - TestMybatis.7z (4.65 MB)

Comment From: spring-projects-issues

jerryscott2014 commented

@Juergen, would you (or someone could solve such issue)mind sparing some time to take a look at such issue ? for in many projects with spring transaction integration, we're confused that the transaction support was not invoked as the configuration or manual described.

first, the code could run just not around the spring transaction so that we should add personal way to cope with the rolling back.

second, it seemed that the component-scan would not completely support or match with the transaction support, maybe we're not sure of the include or exclude filters for those service with the annotation marked. for example:



so I dare say it's important to add such enhancement for that to make sure of the transaction once it was defined and marked around such service (or pointed out the annotation transaction has its limited way, the aop way is recommended)

hibernate or mybatis takes the majorities of the spring-jdbc integration for any way for enhancing that will be much appreciated and popular.

thanks a lot for view

Comment From: spring-projects-issues

Stéphane Nicoll commented

Hi,

I am afraid I am not able to understand your link. If there is something valuable over there please comment here in English. I had a look to your configuration and it has way too many implementation specific details for me to try to reproduce your problem (JtaTransManagerHelper)!

That being said, you have two tx:annotation-driven declaration which will not work. How is that ever supposed to work? If you want to use two different transaction managers in the same application, you have to declare the element with the "main" one and use the qualifier for the other one on @Transactional. Note also that mixing XA and location transactions in the same thread will have side effects and is more than discouraged.

Can you come up with something more reasonable? (removing XA and your specific classes would be a first good step). If you have a sample project that reproduces your issue, this will allow us to fix the issue right the way.

Thanks.

Comment From: spring-projects-issues

jerryscott2014 commented

Thanks for feed back. how comes my reply: First, as for your suggestion, I removed those configuration of the JTA related, but still the transaction didn't apply for such the service around the transaction that is to say it would not be managed by spring.

secondly, the JtaTransManagerHelper is some simple class to create JTA related transaction with the static method as follows: public static TransactionManager createUserTransactionManager(boolean startTransService, boolean forceShutDown) { UserTransactionManager transManager = new UserTransactionManager();

    transManager.setStartupTransactionService(startTransService);

    transManager.setForceShutdown(forceShutDown);

    return transManager;
}

public static UserTransaction createUserTransaction(int transTimeout) throws SystemException {
    UserTransactionImp transImpl = new UserTransactionImp();

    transImpl.setTransactionTimeout(transTimeout);

    return transImpl;
}

thirdly, the jdbc (traditional) transaction and jta transaction won't be mixed together to apply for the same service, as it would refer to different qualifier name service (e.g the jdbc way uses the default transactionManager while the jta uses the jtaTransactionManager). so once those JTA configuration related removed the transaction still not enabled as expected.

at last, as I pointed out and made sure that there were some problem for transaction management for service layer when component scan enabled under the way I listed above. I think you could easily set up such project (while I will make that these days afterwards) to testify that the annotation transaction was easily impacted and disabled though tx-annotation-driven was configured in the applicationContext xml.

Comment From: spring-projects-issues

Stéphane Nicoll commented

Telling me you removed things is not going to help much I am afraid. Please attach a sample project that reproduces the issue you're seeing because I am still not sure to understand what that is.

I confirm that the duplicate tx:annotation-driven entry is wrong and should be removed.

Comment From: spring-projects-issues

jerryscott2014 commented

@Stéphane Nicoll, thanks for quick response.

First , I did remove the duplicate tx:annotation-driven entry for only the jdbc one left alone. by comparison, I tried to replace the tx:annotation-driven with @EnableTransactionManagement(proxyTargetClass=true,mode=AdviceMode.ASPECTJ) and still the log as follows: o.m.s.SqlSessionUtils [SqlSessionUtils.java:140] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ab87b7] was not registered for synchronization because synchronization is not active

o.m.s.t.SpringManagedTransaction [SpringManagedTransaction.java:86] JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@100c71e] will not be managed by Spring

secondly. I dare say the project is not the most important one. and would you mind telling us whether it would fail to brought the transaction around the @Transactional annotated class, are you sure of its use cases to deal with different kinds of things ?

as the project has something to relate with my production environment I just need some time to give a try for re-producing. and I'm sure of its dis-advantages for @Transactional (annotation transaction) while you just could set up such thing as I told.

Comment From: spring-projects-issues

Stéphane Nicoll commented

and would you mind telling us whether it would fail to brought the transaction around the @Transactional annotated class, are you sure of its use cases to deal with different kinds of things ?

We have plenty of tests and tons of use cases where this works so it's close to impossible for me to tell you what's going on with that level of detail.

as the project has something to relate with my production environment I just need some time to give a try for re-producing. and I'm sure of its dis-advantages for @Transactional (annotation transaction) while you just could set up such thing as I told.

Set up what thing exactly? Just to be clear, I am not going to setup anything for the simple reason that I have no idea what you're talking about. This discussion goes in circle: please submit a project that reproduces your issue and we'll be more than happy to have a look to it. Thanks.

Comment From: spring-projects-issues

jerryscott2014 commented

@Stéphane Nicoll , maybe you had misunderstood what I talked about and pointed out. such issue cared about the integration for spring transaction for mybatis or hibernate and especially for mybatis-spring.

First, as I confirmed I did remove the duplicate configuration for tx:annotaiont tag for JTA use cases and it was certain that it had nothing to do with the transaction. things remained the same for the log comment : JDBC Connection will not be managed by Spring

Secondly, please take a look at the mybatis-spring code in github: https://github.com/mybatis/spring/blob/master/src/main/java/org/mybatis/spring/transaction/SpringManagedTransaction.java and please pay more attention to the method : private void openConnection(). the reason for the log comment originated from there where it called the DataSourceUtils.isConnectionTransactional(connection,datasource) from spring jdbc.

Thirdly, as the description above. I did configured everything as the spring manual introduced so it is with mybatis-spring to enable annotation transaction (just as I described in such issue). where it came to the configuration for datasource, transactionManger and tx-annotation driven.

But when I enabled the @ComponetScan from the configuration to scan the package so it was with the service class with @Transactional but when it invoked the mapper calling (just like the mybatis mapper class) which finally it would relate to SpringManagedTransaction the debug showed me that the connection was not around spring. so I felt it was very strange why the service for componet scan did not enable the transaction. for this, I also use @ EnableTransactionManagement for replacement and thing remained still.

After these description above, I think it would help got to know what I talked about and the reference for such log. I just wanted to make sure of the DataSourceUtils.isConnectionTransactional(connection,datasource) and when it was not under spring transaction even if I did configure everything just like datasource or transactionManager.

Comment From: spring-projects-issues

Stéphane Nicoll commented

Once more, please submit a project that reproduces your issue if you want us to investigate further. Besides, you may want to report that issue to mybatis itself: they know their Spring transaction integration code better than we do. Thanks!

Comment From: spring-projects-issues

jerryscott2014 commented

@Stéphane Nicoll , thanks for your advice and I will handle the same issue for mybatis too but I did not think that they would know more than your knowledge and skill for spring transaction integration.

Just I pointed out, they just did some integration relied on spring jdbc iteself. would you mind showing your patience and your professional for the investigation for "DataSourceUtils.isConnectionTransactional(connection,datasource)" processing and leaving me more about such method and giving us more about whether there would some cased cause that connection is not around transaction for I did think it was not some issue with mybatis or hibernate iteslf and I'm sure I was not only the one who was confused by such thing. what's the more, if spring itself could handle such things all, no more issue came up around this.

we dare say that spring team has opened such API public, he or she has the responsibility to accept the doubt or question of the use cases for such and you're the expert for the one.

Comment From: spring-projects-issues

jerryscott2014 commented

@Stéphane Nicoll, here I attach such project but it's not a maven project. and I just uploaded the file related. by the way, there're something you should pay attention to: 1. the lib listed the jars without spring(you could add with your own, the current version is 4.1.3) and jdbc driver (which is oracle for it's large so that I don't upload it)

  1. the script contains the table design which originated from plsql tool

  2. config directory contains the file which you should consider them as the resource file for running.

  3. the entrance test class is TestMain and the log configured at the logback.xml (just set the log level to debug to show whether transaction is enable or not)

Comment From: spring-projects-issues

jerryscott2014 commented

@Stéphane Nicoll, I had uploaded the test project. would you mind spare some time to take a look at it and help locate the problem.

Comment From: spring-projects-issues

jerryscott2014 commented

@Stéphane Nicoll or spring team, I need your help and I had attached the project and hope you could point out if I were wrong with the configuration or use cases with spring transcation

Comment From: spring-projects-issues

Bulk closing outdated, unresolved issues. Please, reopen if still relevant.

Comment From: andotorg

service interface add @Transactional(readOnly = true)