• Spring+Mybatis事务处理


    1、创建数据库表结构如下

    充值及消费记录

    字段名称

    类型

    中文

    长度

    是否主键

    是否自增

    备注

    id

    Int

    Y

    Y

    account

    Varchar

    帐号

    255

    updateTime

    Datetime

    发生时间

    category

    Varchar

    类型

    充值|消费

    num

    int

    数量

    2、使用注解方式整合spring事务,完成如下要求

    1)用户在充值500点券时,由于网格延迟超过了5秒,事务回滚

    2)用户在消费300点券时,没有发生问题,正常提交。记录到用户充值及消费记录表中,并更新用户游戏点券数量

    3、将上述要求改成xml配置方式完成

    package com.xzit.entity;
    
    import lombok.Data;
    import lombok.experimental.Accessors;
    
    @Data
    @Accessors(chain = true)
    public class Account {
        private int id;
        private String account;
        private String password;
        private int coupon;
    }
    package com.xzit.entity;
    
    import lombok.Data;
    import lombok.experimental.Accessors;
    
    import java.util.Date;
    
    @Data
    @Accessors(chain = true)
    public class Records {
        private int id;
        private String account;
        private Date updateTime;
        private String category;
        private int num;
    }
    package com.xzit.mapper;
    
    import com.xzit.entity.Account;
    import org.apache.ibatis.annotations.Update;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    public interface AccountMapper {
        void addAccount(Account account);
        List<Account> selectAccount();
        Account LoginAccount(Account account);
    
        @Update("update day_06_account set coupon=coupon+#{coupon} where account=#{account}")
        void update(Account account);
    }
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.xzit.mapper.AccountMapper">
        <insert id="addAccount" parameterType="Account">
            insert into day_06_account values (null,#{account},#{password},#{coupon})
        </insert>
        <select id="selectAccount" resultType="Account">
            select * from day_06_account
        </select>
        <select id="LoginAccount" resultType="Account" parameterType="Account">
            select * from day_06_account d where d.account = #{account} and d.password = #{password}
        </select>
    </mapper>
    package com.xzit.mapper;
    
    import com.xzit.entity.Records;
    import org.apache.ibatis.annotations.Insert;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface RecordsMapper {
        @Insert("insert into day_06_records values(null,#{account},#{updateTime},#{category},#{num})")
        void insert(Records records);
    }
    package com.xzit.service;
    
    import com.xzit.entity.Account;
    
    import java.util.List;
    
    public interface AccountService {
        void addAccount(Account account);
        List<Account> selectAccount();
        Account LoginAccount(Account account);
    
        void doCharge(String account,int num,String category);
    }
    package com.xzit.service;
    
    import com.xzit.entity.Account;
    import com.xzit.entity.Records;
    import com.xzit.mapper.AccountMapper;
    import com.xzit.mapper.RecordsMapper;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Isolation;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.annotation.Resource;
    import java.util.Date;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    @Service("AccountServiceImpl")
    public class AccountServiceImpl implements AccountService {
        @Resource
        private AccountMapper accountMapper;
    
        @Resource
        private RecordsMapper recordsMapper;
    
        @Override
        public void addAccount(Account account) {
            accountMapper.addAccount(account);
        }
    
        @Override
        public List<Account> selectAccount() {
            return accountMapper.selectAccount();
        }
    
        @Override
        public Account LoginAccount(Account account) {
            Account account1 = null;
            try {
                account1 = accountMapper.LoginAccount(account);
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                if (account1 == null)
                    System.out.println("登录失败,用户名或密码错误");
            }
            return account1;
        }
    
        /* 设置如果超时5秒,事务回滚 */
        @Transactional(
                propagation = Propagation.REQUIRED,
                isolation = Isolation.DEFAULT,
                timeout = 5
        )
        @Override
        public void doCharge(String account,int num,String category) {
            int coupon = num;
            //存一条充值/消费记录
            Records records = new Records();
            records.setAccount(account).setUpdateTime(new Date()).setCategory(category).setNum(num);
            recordsMapper.insert(records);
            System.out.println("执行交易记录处理");
    
            //模拟超时处理
            try {
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            //修改用户原账户下的余额
            Account account1 = new Account();
            account1.setAccount(account);
            account1.setCoupon(coupon);
            accountMapper.update(account1);
            System.out.println("执行了用户余额修改处理");
        }
    }
    package com.xzit.test;
    
    import com.xzit.service.AccountService;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
            /*增加用户*/
            /*Account account = new Account();
            AccountService service = (AccountService) context.getBean("AccountServiceImpl");
            account.setAccount("曾誉").setPassword("1234").setCoupon(5000);
            service.addAccount(account);*/
    
            /*显示用户*/
            /*List<Account> list = service.selectAccount();
            list.forEach(System.out::println);*/
    
            /*用户登录*/
            /*Account account1 = service.LoginAccount(account);
            System.out.println(account1.getAccount()+"登录成功,您的余额为"+account1.getCoupon());*/
    
            /* 用户消费300点券 */
            AccountService service = (AccountService) context.getBean("AccountServiceImpl");
            /*service.doCharge("曾誉",-300,"消费");*/
    
            /* 用户在充值500点券时,由于网格延迟超过了5秒,事务回滚 */
            service.doCharge("曾誉",500,"充值");
        }
    }
    <?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: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/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">
        <!--对应db.properties文件-->
        <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
        <!-- 自动扫描 -->
        <context:component-scan base-package="com.xzit"></context:component-scan>
        <!-- 数据源 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
            <property name="url" value="${jdbc.url}"></property>
            <property name="username" value="${jdbc.username}"></property>
            <property name="password" value="${jdbc.password}"></property>
        </bean>
        <!-- 配置SqlSessionFactory -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
        </bean>
        <!-- 对Mapper的扫描 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
            <!-- 配置Mapper文件的基准包 -->
            <property name="basePackage" value="com.xzit.mapper"></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>
    jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useSSL=false
    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.username=root
    jdbc.password=zengyu1234
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <typeAliases>
            <package name="com.xzit.entity"/>
        </typeAliases>
        <mappers>
            <package name="com.xzit.mapper"/>
        </mappers>
    </configuration>

    使用xml配置实现:

    在pom.xml里添加

    <!--spring aspect-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>5.3.16</version>
            </dependency>

    bean.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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.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 http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
        <!--对应db.properties文件-->
        <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
        <!-- 自动扫描 -->
        <context:component-scan base-package="com.xzit"></context:component-scan>
        <!-- 数据源 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
            <property name="url" value="${jdbc.url}"></property>
            <property name="username" value="${jdbc.username}"></property>
            <property name="password" value="${jdbc.password}"></property>
        </bean>
        <!-- 配置SqlSessionFactory -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
        </bean>
        <!-- 对Mapper的扫描 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
            <!-- 配置Mapper文件的基准包 -->
            <property name="basePackage" value="com.xzit.mapper"></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>-->
        <tx:advice id="myTransaction" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="doCharge" propagation="REQUIRED" timeout="5"/>
            </tx:attributes>
        </tx:advice>
        <aop:config>
            <aop:pointcut id="myPointcut" expression="execution(* *..service..*.*(..))"/>
            <aop:advisor advice-ref="myTransaction" pointcut-ref="myPointcut"></aop:advisor>
        </aop:config>
    </beans>
  • 相关阅读:
    利用同步辅助类CountDownLatch计算多线程的运行时间
    i++的原子性问题
    Volatile关键字以及线程的内存可见性问题
    创建线程的第三种方式以及简单使用
    java8新特性-lambda表达式和stream API的简单使用
    springboot整合activemq
    springboot整合redis单机及集群
    JAVA-基础(一)
    CentOS-文件操作
    理解AngularJS的作用域Scope
  • 原文地址:https://www.cnblogs.com/zengyu1234/p/16449103.html
Copyright © 2020-2023  润新知