Mybatis,Spring集成与事务配置

3 篇文章 2 订阅
2 篇文章 0 订阅

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:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns ="http://www.springframework.org/schema/beans" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:aop="http://www.springframework.org/schema/aop"  
xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:p="http://www.springframework.org/schema/p" 
xmlns:util="http://www.springframework.org/schema/util" 
xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
xmlns:cache="http://www.springframework.org/schema/cache"  
xsi:schemaLocation="  
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.3.xsd    
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx-4.3.xsd  
    http://www.springframework.org/schema/jdbc  
    http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd  
    http://www.springframework.org/schema/cache  
    http://www.springframework.org/schema/cache/spring-cache-4.3.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-4.3.xsd  
    http://www.springframework.org/schema/util  
    http://www.springframework.org/schema/util/spring-util-4.3.xsd">   

	<!-- 1) 扫描注解 -->
	<context:component-scan base-package="com.company.user"/>
	
	<!-- 2) classpath*引入项目下和项目依赖下的属性文件 -->
	<bean id="propertyConfigurer" 
	class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
	<property name="location" value="classpath:jdbc.properties" />
	</bean>
	
	<!--3) 配置数据源-->  
    <bean id="DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    <property name="driverClassName">  
        <value>${jdbc.driverClassName}</value>  
    </property>  
    <property name="url">  
        <value>${jdbc.url}</value>  
    </property>  
    <property name="username">  
        <value>${jdbc.username}</value>  
    </property>  
    <property name="password">  
        <value>${jdbc.password}</value>  
    </property>  
	</bean>  
	
<!-- 4) Mybatis sqlSessionFactory配置 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
	<property name="dataSource" ref="DataSource" />  
        <property name="mapperLocations" value="classpath:com/company/user/mapper/*.xml"></property>   
	</bean>

<!--5) DAO接口所在包名,Spring会自动查找其下的类 -->  
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" >  
    <property name="basePackage" value="com.company.user.mapper" />  
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>  
 
<!--6) (事务管理)transaction manager, use JtaTransactionManager for global tx -->  
    <bean id="transactionManager"  
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
        <property name="dataSource" ref="DataSource" />  
    </bean>

<!-- 7) 添加注解事务-->
<!-- 	<tx:annotation-driven transaction-manager="transactionManager"/>   -->
 
<!--8) 添加规则事务 -->
	<aop:config>
<!-- 	第一个*代表所有的返回值类型  -->
<!-- 	第二个*代表所有的类 -->
<!-- 	第三个*代表类所有方法 最后一个..代表所有的参数。 -->
		<aop:pointcut expression="execution(* com.company.user.service.*.*(..))" id="txPoint"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
	</aop:config>
	
	<tx:advice transaction-manager="transactionManager" id="txAdvice">
		<tx:attributes>
			<tx:method name="find*" propagation="REQUIRED" read-only="true" rollback-for="Throwable"/>
			<tx:method name="insert*" propagation="REQUIRED" rollback-for="Throwable"/>		
		</tx:attributes>
	</tx:advice>
    
</beans>
上述配置中的解释:

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)
或者:

<tx:method name="insert*" propagation="REQUIRED" rollback-for="Throwable"/>

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代理。

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

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

<aop:config proxy-target-class="true">

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

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值