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>

 

posted @ 2022-07-05 23:41  伊万  阅读(199)  评论(0编辑  收藏  举报