事务管理

来源:互联网 发布:制作歌词软件 编辑:程序博客网 时间:2024/05/18 03:58

事务管理

标签: 事务管理 mysql


好看
对登录注册程序添加事务管理:

pom.xml添加:

        <!--aop使用aspectj切入点表达式-->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-aspects</artifactId>            <version>4.1.6.RELEASE</version>        </dependency>

spring-mybatis.xml

<?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:tx="http://www.springframework.org/schema/tx"       xmlns:aop="http://www.springframework.org/schema/aop"       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/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       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">    <!--引入配置文件-->    <context:property-placeholder            ignore-resource-not-found="true"            location="classpath:/db.properties"/>    <!--数据源配置-->    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">        <property name="driverClassName" value="${driver}"/>        <property name="url" value="${url}"/>        <property name="username" value="${jdbc.username}"/>        <property name="password" value="${password}"/>        <property name="maxActive" value="${jdbc.pool.maxActive}"/>        <property name="maxIdle" value="${jdbc.pool.maxIdle}"/>        <property name="minIdle" value="${jdbc.pool.minIdle}"/>        <property name="maxWait" value="${jdbc.pool.maxWait}"/>        <!-- 检查链接是否关闭的sql -->        <property name="validationQuery" value="select 1"/>        <property name="testOnBorrow" value="true"/>    </bean>    <!--mybatis与spring的整合,不需要mybatis自己的配置映射文件-->    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">        <!--配置连接数据库数据源-->        <property name="dataSource" ref="dataSource"/>        <!--配置Mapper文件所在位置-->        <property name="mapperLocations" value="classpath:/mybatis/*Mapper.xml"/>    </bean>    <!--MapperScannerConfigurer将会扫描basePackage并自动装配-->    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">        <property name="basePackage" value="com.wenjie.dao"/>        <!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>-->    </bean>

添加事务管理配置:

    <!-- 配置JDBC数据源的局部事务管理器,使用DataSourceTransactionManager 类 -->    <!-- 该类实现PlatformTransactionManager接口,是针对采用数据源连接的特定实现-->    <bean id="transactionManager"          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <!-- 配置DataSourceTransactionManager时需要依注入DataSource的引用 -->        <property name="dataSource" ref="dataSource"/>    </bean>    <!--配置事务增强处理,指定事务管理器-->    <tx:advice id="myAdvice" transaction-manager="transactionManager">        <tx:attributes>            <tx:method name="*" rollback-for="Exception" propagation="REQUIRED"/>        </tx:attributes>    </tx:advice>    <!-- 配置一个切入点,匹配com.wenjie.service.impl包下所有类,所有方法的执行 -->    <aop:config>        <aop:pointcut id="myPointcut" expression="execution(* com.wenjie.service.impl.*.*(..))"/>        <!-- 通知器,指定在myPointcut切入点应用myAdvice事务增强处理 -->        <aop:advisor advice-ref="myAdvice" pointcut-ref="myPointcut"/>    </aop:config>    <!--由于需要事务控制,所以不能让spring自动扫描注入,spring会把它当做普通bean对象-->    <bean id="loginService" class="com.wenjie.service.impl.LoginServiceImpl"/>    <bean id="registerService" class="com.wenjie.service.impl.RegisterServiceImpl"/></beans>

Propagation取值:

REQUIRED(默认值):在有transaction状态下执行;如当前没有transaction,则创建新的transaction;

SUPPORTS:如当前有transaction,则在transaction状态下执行;如果当前没有transaction,在无transaction状态下执行;

MANDATORY:必须在有transaction状态下执行,如果当前没有transaction,则抛出异常IllegalTransactionStateException;

REQUIRES_NEW:创建新的transaction并执行;如果当前已有transaction,则将当前transaction挂起;

NOT_SUPPORTED:在无transaction状态下执行;如果当前已有transaction,则将当前transaction挂起;

NEVER:在无transaction状态下执行;如果当前已有transaction,则抛出异常IllegalTransactionStateException。

spring-mvc.xml注释service层自动注入

<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xmlns:p="http://www.springframework.org/schema/p"       xmlns="http://www.springframework.org/schema/beans"       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">    <!--自动扫描且只扫描@Controller-->    <context:component-scan base-package="com.wenjie.controller">        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>    </context:component-scan>    <!--对service进行注入-->    <!--<context:component-scan base-package="com.wenjie.service"/>-->    <!-- 激活基于注解的配置 @RequestMapping, @ExceptionHandler,数据绑定 ,@NumberFormat ,    @DateTimeFormat ,@Controller ,@Valid ,@RequestBody ,@ResponseBody等  -->    <mvc:annotation-driven/>    <!-- 视图解析器配置,使用内部资源视图解析器,使用位于/WEB-INF/pages/目录下的后缀为jsp的文件作为视图 -->    <bean id="viewResolver"          class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/pages/"          p:suffix=".jsp"/></beans>

演示RegisterServiceImpl

现在如果RegisterServiceImpl和LoginServiceImpl有异常外抛,则会执行回滚,数据库里面不会进行操作。

package com.wenjie.service.impl;import com.wenjie.dao.UserDao;import com.wenjie.entity.User;import com.wenjie.service.RegisterService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/** * Created by Fate on 2016/7/4. */public class RegisterServiceImpl implements RegisterService {    @Autowired    UserDao userDao;    public boolean register(String username, String password, String age) throws Exception {        User result = userDao.findByName(username);        if (result != null) {            return false;        }        User user = new User();        user.setName(username);        user.setPassword(password);        user.setAge(age);        user.setId(100);        int re = userDao.createUser(user);        userDao.createUser(user);        return re == 1;    }}

利用主键唯一进行测试:

正常事务管理,报错:

1

数据库没有改变:

2

去掉事务管理:

3

也报错:

4

但是数据库插入了第一条数据:

5

注意:

. 如果你在RegisterServiceImpl和LoginServiceImpl中catch 住异常,不再抛出,异常没办法到事务管理器中,就不会触发回滚操作。

. 在配置了事务代理的Service业务逻辑实现类的方法里,若将异常捕获,并且在catch块中不对事务做显式提交(或其他应该做的操作如关闭资源等)=生吞掉异常!

. spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback(Spring默认取决于是否抛出runtime异常或unchecked异常)。如果抛出runtime exception并在你的业务方法中没有catch到的话,事务就会回滚。

. 所以一般不需要在业务方法中catch异常,如果非要catch,在做完你想做的工作后(比如关闭文件等)一定要抛出runtime exception,否则spring会将你的操作commit,这样就会产生脏数据,你的catch代码就是画蛇添足。

. 因此可以在上层做try……catch异常的捕捉处理

. 这里实际上反应了为什么要引入Service层的概念。
将事务管理放在Service层而不是dao层。可以将多次不同dao的操作放到同一个事务里。

0 0