Spring 编程式事物练习,声明式事物的练习,注解事物的练习
Spring 编程式事物的练习,声明式事物的练习,注解事物的练习
上个博客中有建数据库,这里我就不再建了。
一,编程式事物的练习:
导入jar包
<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.6</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.35</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</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>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring -->
<!-- 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>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>5.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jms -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>5.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-messaging -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>5.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-oxm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.25</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
创建Userinfo实体类---与表字段类型一致
package entity;
import java.util.Date;
public class Userinfo {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private Integer money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex == null ? null : sex.trim();
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address == null ? null : address.trim();
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "Userinfo{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
", money=" + money +
'}';
}
}
创建转账接口
package change;
public interface ChangeMoney {
boolean giveMoney(int on, int to, int money);
}
使用generator.xml创建接口的数据库语句
<?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="main"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="main"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="main"
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>
创建运行generator.xml的Generator
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Generator {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("D:\\IDe\\SpringPmtx\\src\\main\\resources\\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);
}
}
将创建的UserinfoMapper.xml放在resources/mapper里,将里面的pojo替换成entity
创建impl实现接口方法
package change;
import entity.Userinfo;
import mapper.UserinfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Component
public class ChangeMoneyImpl_Pmtx implements ChangeMoney {
@Autowired
private UserinfoMapper mapper;
@Autowired
private TransactionTemplate transactionTemplate;
class Result{
boolean result;
}
@Override
public boolean giveMoney(int on, int to, int money) {
final Result result =new Result() ;
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
giveMoneyOption(on, to, money);
System.out.println("=======事务提交了=====");
//事务回滚
result.result = true;
}catch (Exception e){
System.out.println("=======事务回滚了=====");
//事务回滚
transactionStatus.setRollbackOnly();
result.result = false;
}
}
});
return result.result;
}
public void giveMoneyOption(int on, int to, int money) throws Exception {
Userinfo userinfo =mapper .selectByPrimaryKey(on);
int i=0;
if (userinfo!=null){
//设置转钱人的余额
userinfo.setMoney(userinfo.getMoney()-money);
//受影响的行数
i = mapper.updateByPrimaryKey(userinfo);
}
//被转钱人的信息
Userinfo userinfo2 =mapper .selectByPrimaryKey(to);
int j=0;
if (userinfo2!=null){
//设置转钱人的余额
userinfo2.setMoney(userinfo2.getMoney()+money);
//受影响的行数
j = mapper.updateByPrimaryKey(userinfo2);
}
if (i>0&&j>0){
System.out.println("转账成功!!");
}else {
//回滚事务
System.out.println("转账失败!!");
throw new Exception("转账失败的异常");
}
}
}
加入事物管理器
package proxy;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class Proxy_Pmtx implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation method) throws Throwable {
//调用目标方法
Object result = method.proceed();
return result;
}
}
加入beans_Pmtx.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="${uName}" />
<property name="password" value="${password}" />
</bean>
<!-- 3、sqlSessionFactory -->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 别名 -->
<property name="typeAliasesPackage" value="entity"/>
<!-- mapper XML映射 -->
<property name="mapperLocations"
value="classpath*:mapper/*Mapper.xml"></property>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--4、mapper接口的位置 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="mapper"></property>
</bean>
<!-- 1)、事务管理(增强/通知): -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate ">
<property name="transactionManager" ref="txManager"/>
</bean>
</beans>
加入beans_proxy_Pmtx.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:annotation-config/> -->
<context:component-scan base-package="change"/>
<!-- 1)目标 -->
<bean id="target" class="change.ChangeMoneyImpl_Pmtx"/>
<!-- 2)黑客 -->
<bean id="proxy_BC" class="proxy.Proxy_Pmtx"/>
<!--3)代理 -->
<bean id="changeMoney" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="change.ChangeMoney"></property>
<!-- 1)注入目标对象 -->
<property name="target" ref="target"/>
<!-- 2)黑客对象 -->
<property name="interceptorNames">
<array>
<value>proxy_BC</value>
</array>
</property>
</bean>
</beans>
加入database.properties
url=jdbc:mysql://localhost:3306/t142?useUnicode=true&&characterEncoding=utf-8 driver=com.mysql.jdbc.Driver uName=root password=123456
编写测试工具
import change.ChangeMoney;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//编程式事务
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:beans_proxy_Pmtx.xml", "classpath:beans_Pmtx.xml"})
//生成代理的 生成事务管理器(TransactionTemplate)的
public class SpringPmtxTest {
//编程式事务,自己通过aop实现事务管理器
@Autowired
@Qualifier("changeMoney")
private ChangeMoney changeMoney;
@Test
public void test2(){
boolean result = changeMoney.giveMoney(1, 2, 300);
System.out.println(result);
}
}
测试结果
转账成功!! =======事务提交了===== true Process finished with exit code 0
二:声明式事物:
创建impl实现接口方法
package change;
import entity.Userinfo;
import mapper.UserinfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ChangeMoneyImpl_Dlttx implements ChangeMoney {
@Autowired
private UserinfoMapper mapper;
@Override
public boolean giveMoney(int on, int to, int money) {
boolean result=giveMoneyOption(on,to,money);
return result;
}
public boolean giveMoneyOption(int on, int to, int money) {
Userinfo userinfo =mapper .selectByPrimaryKey(on);
int i=0;
if (userinfo!=null){
//设置转钱人的余额
userinfo.setMoney(userinfo.getMoney()-money);
//受影响的行数
i = mapper.updateByPrimaryKey(userinfo);
}
//被转钱人的信息
Userinfo userinfo2 =mapper .selectByPrimaryKey(to);
int j=0;
if (userinfo2!=null){
//设置转钱人的余额
userinfo2.setMoney(userinfo2.getMoney()+money);
//受影响的行数
j = mapper.updateByPrimaryKey(userinfo2);
}
if (i>0&&j>0){
System.out.println("转账成功!!");
return true;
}else {
//回滚事务
System.out.println("转账失败!!");
throw new RuntimeException("转账失败的异常");
}
}
}
加入事物管理器
package proxy;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class Proxy_Dlttx implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation method) throws Throwable {
//调用目标方法
Object result = method.proceed();
return result;
}
}
加入beans_Dlttx.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
https://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
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.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="${uName}" />
<property name="password" value="${password}" />
</bean>
<!-- 3、sqlSessionFactory -->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 别名 -->
<property name="typeAliasesPackage" value="entity"/>
<!-- mapper XML映射 -->
<property name="mapperLocations"
value="classpath*:mapper/*Mapper.xml"></property>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--4、mapper接口的位置 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="mapper"></property>
</bean>
<!-- 1)、事务管理(增强/通知): -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 第1步:定义一个通知 advice -->
<tx:advice id="gmAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 这个方法才会使用事务管理器 -->
<tx:method name="giveMoney*"/>
<!-- 其他任何方法,使用只读事务
isolation="DEFAULT" 事务隔离级别
propagation="REQUIRED" 事务传播特性
timeout="-1" 事务的超时时间
no-rollback-for="" 指定某种运行时异常不回滚
rollback-for="" 指定某种运行时异常才回滚
-->
</tx:attributes>
</tx:advice>
<!-- 第2步:将通知植入切点
public void giveMoney(int a){}
public void change.ChangeMoneyImpl_SM.giveMoney(..)
-->
<aop:config>
<!-- 1)切点-->
<aop:pointcut id="pointCut" expression="execution(* change.ChangeMoneyImpl_Dlttx.*(..))" />
<!-- 2)植入 :将通知植入到切点中-->
<aop:advisor advice-ref="gmAdvice" pointcut-ref="pointCut"/>
</aop:config>
</beans>
加入beans_proxy_Dlttx.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:annotation-config/>
<context:component-scan base-package="change"/>
<!-- 1)目标 -->
<bean id="target_SM" class="change.ChangeMoneyImpl_Dlttx"/>
<!-- 2)黑客 -->
<bean id="proxy_SM" class="proxy.Proxy_Dlttx"/>
<!--3)代理 -->
<bean id="changeMoney_sm" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 接口-->
<property name="proxyInterfaces" value="change.ChangeMoney"/>
<!-- 1)注入目标对象 -->
<property name="target" ref="target_SM"/>
<!-- 2)黑客对象 -->
<property name="interceptorNames">
<array>
<value>proxy_SM</value>
</array>
</property>
</bean>
</beans>
加入database.properties
url=jdbc:mysql://localhost:3306/t142?useUnicode=true&&characterEncoding=utf-8 driver=com.mysql.jdbc.Driver uName=root password=123456
编写测试工具
import change.ChangeMoney;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//编程式事务
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:beans_proxy_Dlttx.xml", "classpath:beans_Dlttx.xml"})
//生成代理的 生成事务管理器(TransactionTemplate)的
public class SpringDlttxTest {
//编程式事务,自己通过aop实现事务管理器
@Autowired
@Qualifier("changeMoney_sm")
private ChangeMoney changeMoney;
@Test
public void test2(){
boolean result = changeMoney.giveMoney(2, 1, 300);
System.out.println(result);
}
}
测试结果
转账成功!! true Process finished with exit code 0
或
转账失败!! java.lang.RuntimeException: 转账失败的异常 at change.ChangeMoneyImpl_Dlttx.giveMoneyOption(ChangeMoneyImpl_Dlttx.java:45) at change.ChangeMoneyImpl_Dlttx.giveMoney(ChangeMoneyImpl_Dlttx.java:17) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498)
三:注解事物
创建impl实现接口方法
package change;
import entity.Userinfo;
import mapper.UserinfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
public class ChangeMoneyImpl_Attx implements ChangeMoney {
@Autowired
private UserinfoMapper mapper;
@Override
@Transactional()
public boolean giveMoney(int on, int to, int money) {
boolean result=giveMoneyOption(on,to,money);
return result;
}
public boolean giveMoneyOption(int on, int to, int money) {
Userinfo userinfo =mapper .selectByPrimaryKey(on);
int i=0;
if (userinfo!=null){
//设置转钱人的余额
userinfo.setMoney(userinfo.getMoney()-money);
//受影响的行数
i = mapper.updateByPrimaryKey(userinfo);
}
//被转钱人的信息
Userinfo userinfo2 =mapper .selectByPrimaryKey(to);
int j=0;
if (userinfo2!=null){
//设置转钱人的余额
userinfo2.setMoney(userinfo2.getMoney()+money);
//受影响的行数
j = mapper.updateByPrimaryKey(userinfo2);
}
if (i>0&&j>0){
System.out.println("转账成功!!");
return true;
}else {
//回滚事务
System.out.println("转账失败!!");
throw new RuntimeException("转账失败的异常");
}
}
}
加入事物管理器
package proxy;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class Proxy_Attx implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation method) throws Throwable {
//调用目标方法
Object result = method.proceed();
return result;
}
}
加入beans_Attx.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
https://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
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.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="${uName}" />
<property name="password" value="${password}" />
</bean>
<!-- 3、sqlSessionFactory -->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 别名 -->
<property name="typeAliasesPackage" value="entity"/>
<!-- mapper XML映射 -->
<property name="mapperLocations"
value="classpath*:mapper/*Mapper.xml"></property>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--4、mapper接口的位置 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="mapper"></property>
</bean>
<!-- 1)、事务管理(增强/通知): -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 声明式事务注解方式:第1步:开启注解事务
proxy-target-class="true" 指定注解事务是使用cglib动态代理方式来实现
-->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
加入beans_proxy_Attx.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:annotation-config/>
<context:component-scan base-package="change"/>
<!-- 1)目标 -->
<bean id="target_ZJSM" class="change.ChangeMoneyImpl_Attx"/>
<!-- 2)黑客 -->
<bean id="proxy_ZJSM" class="proxy.Proxy_Attx"/>
<!--3)代理 -->
<bean id="changeMoney_zjsm" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 接口-->
<property name="proxyInterfaces" value="change.ChangeMoney"/>
<!-- 1)注入目标对象 -->
<property name="target" ref="target_ZJSM"/>
<!-- 2)黑客对象 -->
<property name="interceptorNames">
<array>
<value>proxy_ZJSM</value>
</array>
</property>
</bean>
</beans>
加入database.properties
url=jdbc:mysql://localhost:3306/t142?useUnicode=true&&characterEncoding=utf-8 driver=com.mysql.jdbc.Driver uName=root password=123456
编写测试工具
import change.ChangeMoney;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//编程式事务
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:beans_proxy_Attx.xml", "classpath:beans_Attx.xml"})
//生成代理的 生成事务管理器(TransactionTemplate)的
public class SpringAttxTest {
//编程式事务,自己通过aop实现事务管理器
@Autowired
@Qualifier("changeMoney_zjsm")
private ChangeMoney changeMoney;
@Test
public void test2(){
boolean result = changeMoney.giveMoney(1, 2, 300);
System.out.println(result);
}
}
测试结果
转账成功!! true Process finished with exit code 0
或
转账失败!! java.lang.RuntimeException: 转账失败的异常 at change.ChangeMoneyImpl_Attx.giveMoneyOption(ChangeMoneyImpl_Attx.java:47) at change.ChangeMoneyImpl_Attx.giveMoney(ChangeMoneyImpl_Attx.java:19) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
浙公网安备 33010602011771号