Spring---事务管理练习 (maven)

案例:

  甲乙两个人转钱,正常情况下:甲输入乙的账号,输入金额,然后甲的账户扣除相应的钱,乙的账户扣除相应的钱;
但是就是有特殊情况,甲在输入账号的时候输错了,就会发生一个情况,甲的钱扣掉了,但是乙没有收到钱,肯定就会出现问题;这就是事务相关的问题:

解决办法:

  双方进行转账时其中一方发生异常,及时进行回滚,等待数据正常时在进行提交

 

一、创建进行转账的账号数据库

CREATE TABLE userinfo (
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(255) DEFAULT NULL,
birthday datetime DEFAULT NULL,
sex varchar(1) DEFAULT NULL,
address varchar(255) DEFAULT NULL,
money int(255) DEFAULT NULL,
PRIMARY KEY (id) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

插入数据

INSERT INTO userinfo VALUES (1, ‘旺财’, ‘2020-09-29 00:00:00’, ‘女’, ‘五一广场’, 2100);
INSERT INTO userinfo VALUES (2, ‘来福’, ‘2020-09-16 00:00:00’, ‘男’, ‘五一新干线’, 700);
COMMIT;
主键:SET FOREIGN_KEY_CHECKS = 1;

二、导入相关包

 

<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.11</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>net.sf.ezmorph</groupId>
<artifactId>ezmorph</artifactId>
<version>1.0.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>

<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.2.3</version>
<classifier>jdk15</classifier><!-- 指定jdk版本 -->
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-spec</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.3</version>
</dependency>




</dependencies>
 
   

三、创建一个转账的接口

public interface Changmoney {

boolean giveMoney(int on,int to,int moeny);

}
 
   


四、xml配置

  一.SqlMapConfig.xml

<?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>

<settings>
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--<setting name="aggressiveLazyLoading" value="false"/>-->
<!-- 开启二级缓存总开关 -->
<setting name="cacheEnabled" value="true"/>
<setting name="defaultStatementTimeout" value="25"/>
</settings>
<typeAliases>
<package name="cc.entity"/>
</typeAliases>

<!-- 配置mybatis的环境信息 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源,采用dbcp连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.244.35:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<!-- 加载mapper -->
<mappers>
<!--<mapper resource="sqlmap/User.xml"/>-->
<package name="cc.mapper"/>
</mappers>

</configuration>

  二.创建generator.xml,用mybatis-generator自动生成器数据库简单语句、接口、实现类等

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/t142" userId="root"
password="123456">
</jdbcConnection>
<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
userId="yycg"
password="yycg">
</jdbcConnection> -->

<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>

<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="pojo"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="cc.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="cc.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!--指定数据库表-->
<table tableName="userinfo"
domainObjectName="Userinfo"
enableCountByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
enableUpdateByExample="false"></table>


<!--<table tableName="test" domainObjectName="Test" enableCountByExample="false" enableDeleteByExample="false"-->
<!--enableSelectByExample="false" enableUpdateByExample="false"></table>-->

</context>
</generatorConfiguration>
 
   

  三.用测试类来生成接口和实现类(记得修改包的相关路径)

public static void main(String[] args)  throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("D:\\IDe\\Springzhuangz\\src\\config\\generator.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
 
   

  四.创建实现类

public class ChangeMoneyImpl implements Changmoney {


@Override
public boolean giveMoney(int on, int to, int moeny) {

SqlSession sqlSession = SqlSessionUtil.openSession();

UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);

//转钱人信息
Userinfo userinfo = mapper.selectByPrimaryKey(on);
int i=0;

if (userinfo!=null){

//设置转钱人的余额
userinfo.setMoney(userinfo.getMoney()-moeny);

i = mapper.updateByPrimaryKey(userinfo);

}

//设置被转钱的信息
Userinfo userinfo1 = mapper.selectByPrimaryKey(to);
int j=0;

if (userinfo1!=null){

//设置被转钱人的余额
userinfo1.setMoney(userinfo1.getMoney()+moeny);

//受影响的行数
j = mapper.updateByPrimaryKey(userinfo1);
}


if (i>0&&j>0){
System.out.println("转钱成功");
//sqlSession.commit();
return true;
}else {
System.out.println("转钱失败");
//sqlSession.rollback();
return false;
}

}

}
 
   

  五.创建SqlSessionFactory工厂

public class SqlSessionUtil {
private static SqlSession sqlSession= null;
static {
//1、根据mybaits的配置文件构建SqlSessionFactory
//需要改成我们自己的SqlMapConfig.xml的路径
String resource = "SqlMapConfig.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2、创建SqlSession
sqlSession= sqlSessionFactory.openSession();
}
public static SqlSession openSession() {
return sqlSession;
}

public static void main(String[] args) {
System.out.println(SqlSessionUtil.openSession());
}
}
 
   

  六.测试SqlSessionFactory

Spring---事务管理练习 (maven)

 

 

   测试类+结果

public class TestZhuangz {

public static void main(String[] args) {

Changmoney changmoney = new ChangeMoneyImpl();

boolean b = changmoney.giveMoney(1, 2, 200);
System.out.println(b);

}

}



Spring---事务管理练习 (maven)

 

 

 
   

  七.配置代理事务,配置数据库连接、beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<!--1、加载数据库的配置信息 -->
<context:property-placeholder location="database.properties"/>
<!--2、datasource数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}"/>
<property name="username" value="${username2}"/>
<property name="password" value="${password}"/>
</bean>
<!-- 3、sqlSessionFactory -->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 别名 -->
<property name="typeAliasesPackage" value="com.cc.model"></property>
<!-- mapper XML映射 -->
<property name="mapperLocations" value="classpath*:mapper/*Mapper.xml"></property>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.cc.mapper"></property>
</bean>

<!-- 5、事务管理 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

</beans>

 

 

 

<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 1、启动注解扫描-->
<context:annotation-config/>
<context:component-scan base-package="cc"></context:component-scan>


<!-- 1)目标 -->
<bean id="target" class="cc.change.ChangeMoneyImpl"></bean>
<!-- 2)黑客 -->
<bean id="transactionManager" class="cc.proxy.TransactionManager"></bean>
<!--3)代理 -->

<bean id="ChangeMoneyImpProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="cc.change.Changmoney"></property>
<!-- 1)注入目标对象 -->
<property name="target" ref="target"/>
<!-- 2)黑客对象 -->
<property name="interceptorNames">
<array>
<value>transactionManager</value>
</array>
</property>
</bean>

</beans>
 
   

  八.编写实体代理类

public class TransactionManager  implements MethodInterceptor{

@Override
public Object invoke(MethodInvocation method) throws Throwable {

SqlSession sqlSession = SqlSessionUtil.openSession();
//调用目标方法
boolean result = (boolean) method.proceed();
if( method.getMethod().getName().equals("giveMoney")){
if(result) {
sqlSession.commit();
System.out.println("====提交事务===");
}else {
sqlSession.rollback();
System.out.println("====回滚事务===");
}
}
return result;
}

}
 
   

  九.测试

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration({"classpath:beans.xml"})
public class Test2 {
@Autowired
@Qualifier("ChangeMoneyImplProxy")
changmoney changmoney;
@Test
public void test1(){
boolean b = changmoney.giveMoney(1, 2, 30);
System.out.println(b);
}
}

 
   

  实现

Spring---事务管理练习 (maven)

 

上一篇:maven下 commons-lang3依赖报红问题


下一篇:学习HTML 第三节.接近正题:HTML样式-CSS级联样式表