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>