qiuxuhui

导航

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&amp&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&amp&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&amp&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)

  

 

posted on 2020-12-20 22:07  qiuxuhui  阅读(101)  评论(0编辑  收藏  举报