Mybatis进行事务的管理操作

685 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.注解式声明事物管理

    <!--创建事物管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
</bean>

2.开启事物注解

1.在Spring配置文件,开启事物注解需要引入名称空间tx

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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 https://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

2.创建tx注解开启

 <!--开启事物注解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

3.在Service类上面(或者service类里面的方法上面)添加事物注解

@Transactional
  • 下面为全部代码
  • 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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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 https://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--开启组件扫描-->
    <context:component-scan base-package="com.jdbc.account"></context:component-scan>
    <!--数据库连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
     </bean>
    <!--jdbctemplate对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
     </bean>
    <!--创建事物管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
</bean>
    <!--开启事物注解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

接口

package com.jdbc.account.service;

public interface UserDao {
    //多钱
    public void addMoney();
    //少钱
    public void reduceMoney();
}
  • dao
package com.jdbc.account.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
//多钱
    @Override
    public void addMoney() {
        String sql = "update t_account set money = money+? where username=?";
        jdbcTemplate.update(sql,100,"zhang");
    }
//少钱 l转帐给zhang 100元
    @Override
    public void reduceMoney() {
        String sql = "update t_account set money = money-? where username=?";
        jdbcTemplate.update(sql,100,"lic");
    }
}

  • service
package com.jdbc.account.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class UserService {
    //注入dao
    @Autowired
    private UserDao userDao;

    //转账操作,业务逻辑层
    public void accountMoney() {
        //lic少一百
        int i = 10/0;
        //出先异常进行事物回滚
        userDao.reduceMoney();
        //zhang 多一百
        userDao.addMoney();
    }
}

  • 测试
package com.jdbc.account.service;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class testMoney {
    @Test
    public  void testAccount() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.accountMoney();
    }
}

3.事物操作声明事物管理参数配置

1.在service类上面添加的注解@Transactional,这个注解里面的参数配置

图片.png

  • propagation:事物传播行为:多事物方法直接调用,这个过程中事物是如何管理

事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。spring支持7种事务传播行为:

  • propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
  • propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。 propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
  • propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
  • propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
  • propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与

propagation_required类似的操作Spring 默认的事务传播行是PROPAGATION_REQUIRED,它适合于绝大多数的情况。假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring 事务增强了),假设程序中存在如下的 调用链:Service1#method1()->Service2#method2()->Service3#method3(),那么这 3 个服务类的 3个方法通过 Spring 的事务传播机制都工作在同一个事务中。

  • ioslation:事物隔离性 事物有特性成为隔离性,多事物操作之间不会产生影响,不考虑隔离性产生很多问题 1.胀读:一个未提交的事物读取到另一个未提交事物的数据 2.不可重读:一个未提交的事物读取到另一个提交事物修改的数据 3.虚度:一个未提交事物读到另一个提交事物添加数据 4.解决:通过设置事物隔离级别,解决读问题
脏读不可重读幻读
READ UNCOMMITTED(读未提交)
READ COMMITTED(读已提交)
REPEATABLE READ(可重复读)
SERIALIZABLE(串行化)

例如:设置隔离级别,MySQL默认是未REPEATABLE READ (可重读)

@Service
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class UserService {
  • timeout :超时时间 1.事物需要在一定的时间类进行提交,如果不提交就进行回滚,其默认值为-1,设置时间以秒为单位进行计算

图片.png

  • readOnly :是否只读 1.读:查询操作,写:添加修改操作 2.readOnly默认值是false,表示可以查询,可以添加修改删除操作,当设置为true是只能查询

  • rollbackFor :回滚 1.设置出现那些异常进行事物回滚

  • noRollbackFor :不回滚 1.设置出现那些异常不进行事物回滚

4.事物操作基于xml声明事物管理

1.在Spring配置文件进行配置

  • 1.配置事物管理器
  • 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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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 https://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--开启组件扫描-->
    <context:component-scan base-package="com.jdbc.account"></context:component-scan>
    <!--数据库连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
     </bean>
    <!--jdbctemplate对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
     </bean>
    <!--配置创建事物管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
</bean>
 <!--配置通知-->
    <tx:advice id="txadvice">
        <!--配置事物参数-->
        <tx:attributes>
            <!--指定那这规则的方法上面添加事物-->
            <tx:method name="accountMoney" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--配置切入点和切面-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pt" expression="execution(* com.jdbc.account.service.UserService.*(..))"/>
        <!--配置切面-->
        <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
    </aop:config>
</beans>

进行测试

  • 接口类
package com.jdbc.account.service;

public interface UserDao {
    //多钱
    public void addMoney();
    //少钱
    public void reduceMoney();
}

  • dao
package com.jdbc.account.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
//多钱
    @Override
    public void addMoney() {
        String sql = "update t_account set money = money+? where username=?";
        jdbcTemplate.update(sql,100,"zhang");
    }
//少钱 l转帐给zhang 100元
    @Override
    public void reduceMoney() {
        String sql = "update t_account set money = money-? where username=?";
        jdbcTemplate.update(sql,100,"lic");
    }
}

  • service
package com.jdbc.account.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
//@Transactional(timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class UserService {
    //注入dao
    @Autowired
    private UserDao userDao;

    //转账操作,业务逻辑层
    public void accountMoney() {
        //lic少一百
        int i = 10/0;
        //出先异常进行事物回滚
        userDao.reduceMoney();
        //zhang 多一百
        userDao.addMoney();
    }
}

  • 测试
package com.jdbc.account.service;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class testMoney {
    @Test
    public  void testAccount() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.accountMoney();
    }
}

实现回滚,数据库不变

图片.png

5.事物操作完全注解声明式事物管理

1.创建配置类,使用配置类代替xml配置文件

package com.jdbc.account.service;


import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration //配置类
@ComponentScan(basePackages = "com.jdbc") //开启组件扫描
@EnableTransactionManagement //开启事物
public class TxConfig {
    //创建数据库连接池
    @Bean
    public DruidDataSource getDruidDataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/test");
        druidDataSource.setName("root");
        druidDataSource.setPassword("");
        return druidDataSource;
    }
    //创建jdbcTemplate对象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        //到ioc容器中根据类型找到dataSource
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        //注入dataSource
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;

    }
    //创建事物管理器
    public DataSourceTransactionManager getDateSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}

4.还有什么问题可以留言给我,会尽心解答的,觉得文章不错的话点个赞把