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等的配置。