今天把框架整合完毕,测试时发现,无论使不使用aop还是@Transactional,service层中的对应新增等方法都会保存成功。跟踪代码发现在org.mybatis.spring.SqlSessionTemplate这个类中,当运行service层中的相应方法时会调用SqlSessionInterceptor这个内部类的invoke方法如下:

private class SqlSessionInterceptor implements InvocationHandler {

		public Object invoke(Object proxy, Method method, Object args[])
            throws Throwable
        {
            SqlSession sqlSession = SqlSessionUtils.getSqlSession(sqlSessionFactory, executorType, exceptionTranslator);
            Object obj;
            try
            {
                Object result = method.invoke(sqlSession, args);
                if(!SqlSessionUtils.isSqlSessionTransactional(sqlSession, sqlSessionFactory))
                    sqlSession.commit(true);
                obj = result;
            }
            catch(Throwable t)
            {
                Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
                if(exceptionTranslator != null && (unwrapped instanceof PersistenceException))
                {
                    SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
                    sqlSession = null;
                    Throwable translated = exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);
                    if(translated != null)
                        unwrapped = translated;
                }
                throw unwrapped;
            }
            if(sqlSession != null)
                SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
            return obj;
            Exception exception;
            exception;
            if(sqlSession != null)
                SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
            throw exception;
        }

		final SqlSessionTemplate this$0;

		private SqlSessionInterceptor() {
			this$0 = SqlSessionTemplate.this;
			super();
		}

	}

当运行到

 if(!SqlSessionUtils.isSqlSessionTransactional(sqlSession, sqlSessionFactory))

这行代码时一直返回false,也就是说Spring并没有接管MyBatis的事务。

    再上网查资料,后来检查发现是因为Spring MVC扫描的问题。先说下我的配置文件,我在web.xml中配置一个Spring配置件contextConfigLocation.xml其中没有对包做扫描,然后SpringMVC会自动加载以项目名-servlet.xml的配置文件,我在此文件中的扫描代码如下:

wKiom1Q5ABSDWYa0AABqx9Pgqos728.jpg

因为加载的问题结果导致service中得不到Spring的事务,最后解决办法:

contextConfigLocation.xml中新增扫描service的代码

wKioL1Q5AMrjkB9yAADoN2LXOwo069.jpg默认的项目名-servlet.xml中修改如下:

wKiom1Q5ANTCJqpCAAD7BdoqW7k334.jpg

重新测试就好了。个人猜测是加载顺序导致的,上网查过,Spring优先级大于SpringMVC。有兴趣的朋友可以参考这个链接:http://www.iteye.com/topic/1125421,因为事务控制是声明在contextConfigLocation.xml文件中,所以需要在这个文件中加入service的初始化。补充:如果去掉web.xml中对于contextConfigLocation这个listener的配置也就是说在项目启动时只会加载默认的项目名-servlet.xml文件时,全部配置都由此文件进行初始化时就不需要特别说明spring扫描排除哪个和包含哪个了。

    以上是个人的一点看法,如果有大牛觉得不合理,欢迎留言。