Mybatis,Spring集成与事务配置

Mybatis,Spring集成与事务配置

这篇主要讲两个问题,一个是Spring与Mybatis的集成,另一个是Mybatis与Spring的事务配置

一.Mybatis与Spring的集成,需要先掌握的

1.关于Mybatis的配置和使用见上篇文章http://blog.csdn.net/Jintao_Ma/article/details/52829490 ; 

2.如何创建Maven项目http://blog.csdn.net/Jintao_Ma/article/details/52141802 

集成后的项目可以在这里下载http://download.csdn.net/download/jintao_ma/9657385,主要分析的是Spring与Mybatis结合后的配置文件 Spring_Mybatis.xml:

  
   

	
	
	
	
	
	
	
	
	  
      
      
        ${jdbc.driverClassName}  
      
      
        ${jdbc.url}  
      
      
        ${jdbc.username}  
      
      
        ${jdbc.password}  
      
	  
	

	  
	  
           
	

  
      
      
    
      
 
  
      
          
    



 

	



		
		
	
	
	
		
			
					
		
	
    
上述配置中的解释:

1)不用解释了,就是扫描所有加上注解的java类

2)和3)是配置数据源的另一种方式,先把数据库连接信息放入属性文件,然后在数据源中使用。 和上篇文章的不同

4)这个配置的意义其实就完全等同于上篇文章中的configuration.xml,指定数据源来对mapper中的sql语句进行实现,然后用SqlSessionFactoryBuild加载后,返回SqlSessionFactory,这就是这个配置的含义。同上面文章中的:

private static SqlSessionFactory getSessionFactory() {    
        SqlSessionFactory sessionFactory = null;    
        String resource = "configuration.xml";    
        try {    
            sessionFactory = new SqlSessionFactoryBuilder().build(Resources    
                    .getResourceAsReader(resource));  
        } catch (IOException e) {    
            e.printStackTrace();    
        }    
        return sessionFactory;

5)这个配置的意义完全等同于上篇文章中通过sqlSessionFactory得到SqlSession,然后通过SqlSession.getMapper(“类名”)的方式得到mapper的代理,就可以直接使用mapper中的方法。同上篇文章中的:

SqlSession sqlSession = getSessionFactory().openSession();    
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

 本篇的这个配置直接把SqlSessionFactory中的所有mapper的实现与具体的mapper接口的名字对应起来,并且把这个mapper接口的名字作为Spring中mapper实现的Bean名称,这样在使用的时候就可以使用诸如下面的方式进行注入:

	@Autowired
	private UserMapper userMapper;

二.Spring对Mybatis的事务管理

关于事务,前面的文章有讲述过:http://blog.csdn.net/Jintao_Ma/article/details/51243372

1.Mybatis本身事务需要手动提交,然后关闭事务,在和Spring集成后由Spring来管理, 6)这个配置含义就是把数据源交给Spring的事务管理器来进行管理。配置7)指定使用注解的方式来管理事务,形如下面的方式:

@Transactional(rollbackFor=Exception.class)
	public void insertTwo() 
2.配置8)使用另一种方式来配置事务,aop:config中

A)指定“切点”,确定在哪个类的哪个方法中切入事务

B)指定“通知器”,这个通知器表明切点,和在切点处应该做的事情("通知")

tx:advice  就是“通知”,我们在这里面进行方法的回滚,这样的话也完成了事务的配置,方法中自动添加事务,也不需要注解之类。如:

public void insertTwo()

只不过在配置8中要注意一下的几点(转自:http://blog.csdn.net/superdog007/article/details/50315319

A).想必大家都用了springMVC,并且使用了其扫描器组件,对项目中加入servcie /ctroller注解的bean进行注册交给srping容器管理,在springMVC配置文件中我们只扫描ctroller对所有的service进行过滤掉,因为按照spring配置文件的加载顺序来讲,先加载springmvc配置文件,再加载spring配置文件,我们的事物一般都在srping配置文件中进行配置,如果此时在加载srpingMVC配置文件的时候,把servlce也给注册了,但是此时事物还没加载,也就导致后面的事物无法成功注入到service中。所以把对service的扫描放在spring配置文件中或是其他配置文件中,这篇文章中有详细介绍:http://blog.csdn.net/mmm333zzz/article/details/16858209

B).如果以上步骤都没问题,事物还是失效,查看事物配置中的excution表达式路径是否正确,查看rollback-for指定的异常类是否有,通过Log4j ,debug模式将事物日志打印出来,在方法中手动new一个异常抛出(throw new RuntimeException())看是否事物回滚了,注意异常抛出要在service层

C).如果你用了mysql数据库,查看数据库存储引擎,MyISAM是不支持事物的,需要改成InnoDB(自己就是在这个地方出了问题,创建表格的时候指定是InnoDB,创建完成之后引擎就变成了MyISAM,原来InnoDB被禁止了~~)

3.除了7和8两种事务管理方式外,Spring还有几种事务管理方式,只是配置7是配置最少的,配置8则清晰明确,这两种是最常用的事务配置方式。

三.一些思考

1.try...catch应不应该写在事务层? 

仔细想一下,事务层一般就是业务层,try...catch在业务层是不是真的有必要?比如,我们在try中遇到了一个异常,但是我们catch的时候并不能保证的处理好,所以应该在保证能处理好这个异常的情况下进行catch,如服务器连接不上,而且catch之后一定要进行处理,如重新尝试连接服务器。 而对于那些不能处理的异常,就应该直接抛出,由service层抛到controller层,然后由controller层进行try...catch,记录日志,并且返回给UI。 通常情况下的异常,都是catch后处理不好的异常,所以改直接抛出。

答案是,service层throw,controller层进行try...catch。至于有些人说try...catch后可以记录异常,问题是到了controller依然可以啊,整个异常堆栈又不会变~

2.为什么看到很多事务的配置都是Exception?

当在使用注解的时候,一般都是指定rollbackFor=Exception.class,或者在配置aop:config时候,也是使用rollback-for="Exception",我很不理解。 当我们不指定回滚类型的时候,默认的是对unchecked异常+error进行回滚,现在我们指定了为Exception(checded异常+unchecked异常,那error哪里去了),难道我们不应该指定rollback-for="Throwable"吗。

个人以为正确的答案是:

@Transactional(rollbackFor=Throwable.class)
或者:

3.对于sql查询语句需要设置事务吗?

这些语句可以不启动事务,也可以启动事务设置read-only为true;当加上read-only为true时:

1)不会滚事务

2)进行数据库查询优化

答案是:设置read-only为true可以使用数据库增加了一下优化

4.aop代理分为jdk接口代理和cglib类代理,通过什么来控制它使用哪一个?

答案是:通过proxy-target-class来控制,proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。即使你未声明 proxy-target-class="true" ,但运行类没有继承接口,spring也会自动使用CGLIB代理。

针对本篇的两种事务配置方式,形如:

总结:关于Mybatis与Spring集成的总结大概就是这些了,后面提出的一些思考,如果有问题,希望指出,共同学习~~ 后面也会以先分析源码,再梳理框架的形式,加上SpringMVC和Shiro等的配置。 

你可能感兴趣的:(Spring,Mybatis,Java框架)