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;

插入数据:BEGIN;
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;

二、

在这之前大家记得导入相关架包(因为使用的是maven空间,大家架包可以去maven中央仓库去下载

这里是maven仓库链接

三、创建一个转账的接口
在这里插入图片描述
四、配制数据库连接

<?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"/>
    </settings>

    <typeAliases>
        <package name="pojo"/>
        <package name="vo"/>
    </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://localhost:3306/userinfo?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 加载mapper -->
    <mappers>
        <!--<mapper resource="sqlmap/User.xml"/>-->
        <package name="mapper"/>
    </mappers>

</configuration>

五、使用MyBateis来生成数据库相关语句、接口、实现类等

<?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/userinfo"
                        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="po"
                            targetProject=".\src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- targetProject:mapper映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject=".\src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        <!-- targetPackage:mapper接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="mapper"
                             targetProject=".\src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>

        <table tableName="userinfo"
               domainObjectName="Userinfo"
               enableCountByExample="false"
               enableDeleteByExample="false"
               enableSelectByExample="false"
               enableUpdateByExample="false"/>
    </context>
</generatorConfiguration>

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

    @Test
    public void testMBG() throws Exception{
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File("mbg.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);
    }
    
}
生成了之后大家记得改变包的位置不然怕加载不了

六、创建实现类

@Configuration
public class ChangeMoneyImpl implements changmoney {


    @Override
    public boolean giveMoney(int on, int to, int money) {
        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()-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("转钱成功");
            //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 
        //需要改成我们自己的mybatis-config.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;
    }
}

测试是可以转转成功的
在这里插入图片描述
接下来配置代理事务了

首先配置数据库连接

<?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>
url=jdbc:mysql://localhost:3306/userinfo?useUnicode=true&amp&characterEncoding=utf-8
driver=com.mysql.jdbc.Driver
username2=root
password=123456

接下来就是配置事务代理

<?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"></context:component-scan>

       
       <!-- 1)目标 -->
       <bean id="target" class="change.ChangeMoneyImpl"></bean>
       <!-- 2)黑客 -->     
       <bean id="transactionManager" class="proxy.TransactionManager"></bean>
       <!--3)代理  -->  
       
     <bean  id="ChangeMoneyImplProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces"  value="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(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);
    }
}

所得结果为
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 2019年黑马项目-畅购商城springcloud微服务实战是一门以实战为主的课程,旨在通过项目实践的方式,帮助学员深入理解和掌握SpringCloud微服务架构以及相关技术的应用。 课程的主要内容包括搭建基础的微服务架构、使用SpringCloud构建服务注册与发现、实现服务间的负载均衡、实现分布式配置中心、服务间的调用与容错处理、使用网关统一接入服务等。通过这些实战练习,学员不仅能够熟悉SpringCloud架构与组件,还能够了解微服务架构下的常见问题与解决方案。 畅购商城项目是一个典型的电商应用,通过实现该项目,学员可以接触到真实的业务场景与需求,并能够将所学知识应用到实际项目中。课程中通过模块化的方式逐步完善商城的功能,包括用户注册登录、商品浏览、购物车管理、订单生成与支付等。通过这些实践,学员除了掌握SpringCloud微服务的开发技术,还能够了解和掌握电商项目的开发流程和注意事项。 该课程的目标是让学员通过实战项目,全面了解和掌握SpringCloud微服务架构的设计与开发,在此基础上能够独立完成具有较高要求的微服务项目。通过参与实战项目的过程,学员还能够提升团队协作能力、解决问题的能力以及项目管理能力。 通过这门课程的学习,学员将会对SpringCloud微服务架构有更深入的理解,并能够将这些知识应用到实际项目中,提高自己在微服务开发领域的竞争力。 ### 回答2: 2019年黑马项目-畅购商城springcloud微服务实战是一个基于springcloud微服务架构的商城项目。该项目的目标是通过运用微服务的理念和技术,构建一个高可用、可扩展的商城系统。 在该项目中,使用了springcloud的多个组件,如Eureka注册中心、Feign负载均衡、Ribbon客户端负载均衡、Hystrix服务降级和容错、Zuul网关等。这些组件共同协作,实现了系统的弹性伸缩和高可用性。 畅购商城的功能包括商品展示、购物车、订单管理、支付、用户管理等。通过将这些功能拆分成独立的微服务,使得系统更加灵活和可维护。同时,使用分布式事务和消息队列来保障数据的一致性和可靠性。 在项目的开发过程中,采用了敏捷开发的方法,以迭代的方式进行开发和测试。通过使用Jenkins进行持续集成和部署,保证了代码的质量和系统的稳定性。 在项目的实战过程中,面临了许多挑战和困难,如微服务之间的通信、服务的负载均衡、服务的容错等。但通过团队的共同努力和不断的学习,最终成功地完成了该项目的开发和部署。 在该项目的实施过程中,不仅学到了springcloud微服务架构的相关知识和技术,还体会到了团队合作和解决问题的能力。该项目的成功实施,不仅为公司带来了商业价值,也提升了团队的技术水平和项目管理能力。 ### 回答3: 2019年黑马项目-畅购商城springcloud微服务实战是一个以Spring Cloud为基础的微服务项目。微服务架构是一种将应用拆分成多个小型服务的架构模式,这些服务可以独立开发、部署、扩展和管理。 畅购商城项目使用了Spring Cloud的一系列子项目,如Eureka、Ribbon、Feign、Hystrix、Zuul等,来实现各个微服务之间的通信、负载均衡、服务降级与熔断等功能。 在项目中,我们会通过Eureka来实现服务的注册与发现,每个微服务都会向Eureka注册自己的地址,其他微服务可以通过Eureka来发现并调用这些服务。而Ribbon则负责实现客户端的负载均衡,可以轮询、随机、加权等方式分发请求。 Feign是一种声明式的HTTP客户端,它简化了服务间的调用方式。我们只需编写接口,并通过注解来描述需要调用的服务和方法,Feign会自动实现远程调用。 Hystrix是一个容错机制的实现,可以通过断路器来实现服务的降级与熔断,当某个服务出现故障或超时时,Hystrix会快速响应并返回一个可控制的结果,从而保证系统的稳定性。 另外,Zuul作为微服务网关,可以实现请求的统一入口和路由转发,提高系统的安全性和性能。 通过这些Spring Cloud的组件,畅购商城项目可以实现高可用、容错、自动扩展等优质的微服务架构。 总之,2019年黑马项目-畅购商城springcloud微服务实战是一个基于Spring Cloud的微服务项目,通过使用Spring Cloud的各个子项目,可以实现微服务之间的通信、负载均衡、服务降级与熔断等功能,为项目的开发、部署和管理提供了便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值