Spring(三)事务处理、整合Mybatis
2018-12-10 本文已影响18人
一直想上树的猪
一、事务处理
1.事务传播行为
一共七种:
- PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是 最常见的选择。
- PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED 类似的操作。
2.事务隔离级别
Isolation 属性一共支持五种事务设置,具体介绍如下:
- DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .
- READ_UNCOMMITTED 未提交读 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )
- READ_COMMITTED 已提交读 会出现不可重复读、幻读问题(锁定正在读取的行)
- REPEATABLE_READ 可重复读 会出幻读(锁定所读取的所有行)
- SERIALIZABLE 可序列化 保证所有的情况不会发生(锁表)
3.几种事务出现问题的区别
不可重复读的重点是修改
同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了
幻读的重点在于新增或者删除
同样的条件 , 第 1 次和第 2 次读出来的记录数不一样
4.Spring在TransactionDefinition接口中定义这些属性
在TransactionDefinition接口中定义了五个不同的事务隔离级别
- ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
- ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它允许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读
- ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
- ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
- ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
5.Spring中的声明式事务控制
Spring中控制事务的方式采用声明式的事务控制。为我们提供了不同的事务控制器的切面(注意:spring的事物控制器就是一个aop,如果面试时问你是否用spring的aop 。一定要回答用过,起码事务上用到了。)
6.配置Spring的基于dataSourse的事务控制器,适用于jdbc、mybatis,DataSourceAransactionManager:基于数据源的事务控制的切面
7.代码实现
1.导入jar包:
spring-jdbc.jar
spring-tx.jar
spring-aop.jar
2.在spring的配置文件中配置事务
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 需要在配置文件的头中开启tx的命名空间 -->
<!-- 先配置基于dataSource的事务管理器的切面(AOP)-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 该切面需要一个datasource -->
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<!-- 配置事物传播行为以及事物隔离级别 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
name:需要参与到事物控制中的方法名。可以使用*来通配
propagation:事物的传播行为。REQUIRED 必须要运行在一个事务中
isolation:事物的隔离级别 。DEFAULT以数据默认的隔离级别为主。
read-only:只读事物。只读并不会做事物提交与回滚。他会优化查询执行的效率。所以如果不是DML操作。建议都需要拥有只读事物
-->
<tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="drop*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置切点 -->
<aop:config>
<aop:pointcut expression="execution(* com.tinner.service.impl.*.*(..))" id="mypointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypointcut"/>
</aop:config>
</beans>
二、整合mybatis
1.在实现Spring与Mybatis的整合时,需要导入两个框架的jar包。注意:spring与mybatis整合时,需要额外导入一个非常重要的jar包 spring-mybatis.jar
2.Spring中提供三种方式
2.1 sqlSessionTemplate
Autowire属性:自动装配
1。byName通过名称完成自动注入。要求注入与被注入的属性的名称相同
2。byType 通过类型完成自动注入。要求名称可以不相同,但是类型必须是同类型,或者是父类,或者已实现的接口类型。
default-autowire :<beans>标签中的该属性表示全局性的自动装配的设置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 通过命名空间配置解析配置文件的工具类 -->
<context:property-placeholder location="/db.properties"/>
<!-- 配置数据源。dbcp c3p0 druid。。。 -->
<!-- 配置数据源 dataSource -->
<!-- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="maxActive" value="10" />
<property name="minIdle" value="5" />
</bean> -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test001"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 配置创建mybatis上下文对象的工具类 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
<!-- 配置datasource -->
<property name="dataSource" ref="dataSource"/>
<!-- 导入其他配置文件 -->
<property name="mapperLocations" value="com/tinner/pojo/*.xml"/>
</bean>
<!-- 配置sqlsessiontemplate -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 通过构造方法完成sqlsessionfactory的注入 -->
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!-- 配置userdao -->
<bean id="userDao" class="com.tinner.dao.impl.UserDaoImpl" autowire="byName"/>
</beans>
2.2 SqlSessionDaoSupport方式
配置文件:
<!-- 配置创建mybatis上下文对象的工具类 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
<!-- 配置datasource -->
<property name="dataSource" ref="dataSource"/>
<!-- 导入其他配置文件 -->
<property name="mapperLocations" value="com/tinner/pojo/*.xml"/>
</bean>
<!-- 配置userdao -->
<bean id="userDao" class="com.tinner.dao.impl.UserDaoImpl" >
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
代码:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
//将SqlSessionFactory交给SqlSessionDaoSupport
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
@Override
public void insertUser(Users user) {
this.getSqlSession().insert("com.tinner.pojo.Users.insertUser", user);
}
}
2.3 使用代理类生成接口实现类的方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 通过命名空间配置解析配置文件的工具类 -->
<context:property-placeholder location="/db.properties"/>
<!-- 配置数据源。dbcp c3p0 druid。。。 -->
<!-- 配置数据源 dataSource -->
<!-- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="maxActive" value="10" />
<property name="minIdle" value="5" />
</bean> -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test001"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 配置创建mybatis上下文对象的工具类 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
<!-- 配置datasource -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置扫描接口与映射配置文件对象 该对象会去创建接口的代理对象。并且根据接口的名称作为该对象的默认名称-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.tinner.mapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>