美文网首页
小案例-转账

小案例-转账

作者: Fultom | 来源:发表于2019-12-04 11:22 被阅读0次

转账

1.1 搭建环境

创建表

CREATE DATABASE ee19_spring_day03;
USE ee19_spring_day03;
CREATE TABLE account(
    id INT PRIMARY KEY auto_increment,
    username VARCHAR(50),
    money INT
);
INSERT INTO account(username,money) VALUES('jack','10000');
INSERT INTO account(username,money) VALUES('rose','10000');

1.2.1 Dao层

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
    @Override
    public void out(String outer, Integer money) {
        this.getJdbcTemplate().update("update account set money = money - ? where username = ?",money,outer);

    }

    @Override
    public void in(String inner, Integer money) {
        this.getJdbcTemplate().update("update account set money = money + ? where username = ?",money,inner);
    }
}

1.2.2 service层

public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String outer, String inner, Integer money) {
        accountDao.out(outer,money);
        // 断电
//        int i=1/0;
        accountDao.in(inner,money);
    }
}

1.2.3 spring配置文件

 <!--DataSource-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ee19_spring_day03"></property>
        <property name="user" value="root"></property>
        <property name="password" value="12345678"></property>
    </bean>

    <!--dao-->
    <bean id="accountDao" class="com.xft.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--service-->
    <bean id="accountService" class="com.xft.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

1.2.4 测试

public class TestApp {
    @Test
    public void demo01(){
        String xmlPath = "applicationContext.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        AccountService accountService = applicationContext.getBean("accountService",AccountService.class);
        accountService.transfer("jack","rose",100);
    }
}

1.3 手动管理事务

  • spring底层使用TransactionTemplate 事务模板进行操作
  • 操作
  1. 需要获得TransactionTemplate
  2. spring配置模板,并注入给service
  3. 模板需要注入事务管理器
  4. 配置事务管理器DataSourceTransactionManager,需要注入DataSource

1.3.1 修改service


    //需要spring注入模板
    private TransactionTemplate transactionTemplate;
    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    public void transfer(String outer, String inner, Integer money) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                accountDao.out(outer,money);
                // 断电
//        int i=1/0;
                accountDao.in(inner,money);
            }
        });
    }

1.3.2 修改spring配置


    <!--service-->
    <bean id="accountService" class="com.xft.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
        <property name="transactionTemplate" ref="transactionTemplate"></property>
    </bean>

    <!--创建模板-->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="txManager"></property>
    </bean>

    <!--配置事务管理器 管理器需要事务,事务从Connection获得,连接从连接池DataSource获得 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

1.4 工厂 bean 生成代理:半自动

  • spring提供 管理事务的代理工厂 bean TransactionProxyFactoryBean
  1. getBean() 获得代理对象
public class TestApp {
    @Test
    public void demo01(){
        String xmlPath = "applicationContext.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        AccountService accountService = applicationContext.getBean("proxyAccountService",AccountService.class);
        accountService.transfer("jack","rose",100);
    }
}
  1. spring配置一个代理
<!--4 service 代理对象
        4.1  proxyInterfaces接口
        4.2  target目标类
        4.3  transactionManager 事务管理器
        4.4  transactionAttributes 事务属性(事务详情)
             prop key :确定哪些方法使用当前事务配置
             prop.text: 用于配置事务详情
                格式: PROPAGATION,ISOLATION,readOnly,-Exception,+Exception
                        传播行为    隔离级别    是否只读    异常回滚    异常提交
                例如:<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly</prop> 默认的传播行为和隔离级别
    -->
    <bean id="proxyAccountService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="proxyInterfaces" value="com.xft.service.AccountService"></property>
        <property name="target" ref="accountService"></property>
        <property name="transactionManager" ref="txManager"></property>
        <property name="transactionAttributes">
            <props>
                <prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
            </props>
        </property>

    </bean>

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

1.5 AOP 配置基于xml(重要)

  • 在spring xml配置aop自动生成代理,进行事务的管理
  1. 配置管理器
  2. 配置事务详情
  3. 配置aop
<!--==============aop配置=================-->
    <!--4 事务管理-->
    <!--4.1 事务管理器-->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--4.2 事务详情(事务通知) ,在aop筛选的基础上,对abc 三个确定使用什么样的事务 例如ac 读写 b只读
        <tx:attributes> 用于配置事务详情(事务属性)
        <tx:method name="transfer"/> 详情的具体配置
            propagation 传播行为 REQUIRED:必须
            issolaton  隔离级别
    -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="transfer" propagation="REQUIRES_NEW" isolation="DEFAULT"/>
        </tx:attributes>
    </tx:advice>


    <!--4.3 AOP 编程目标有abcd(四个切入点),切入点表达式确定增强的连接器 从而获得切入点ABC-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.xft.service..*.*(..))"/>
    </aop:config>

1.6 AOP 配置基于注解[重要]

  • 配置事务管理器,并将事务管理器交于 spring
  • 在目标类或目标方法添加注解即可 @Transactional
 <!--4 事务管理-->
    <!--4.1 事务管理器-->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--4.2 将管理器交于spring
        transaction-manager 配置事务管理器
        proxy-target-class true : 底层强制使用cglib 代理
    -->
    <tx:annotation-driven transaction-manager="txManager"/>

service 层

@Transactional
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    //需要spring注入模板
    private TransactionTemplate transactionTemplate;
    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }


    @Override
    public void transfer(String outer, String inner, Integer money) {
 doInTransactionWithoutResult(TransactionStatus transactionStatus) {

        accountDao.out(outer,money);
        // 断电
//                int i=1/0;
        accountDao.in(inner,money); 
    }
}

1.7整合Junit

  1. 让Junit通知spring加载配置文件
  2. 让spring容器自动进行注入
  • 修改测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext2.xml")
public class TestApp {

    @Autowired //与junit整合,不需要再spring xml设置扫描
    private AccountService accountService;
    @Test
    public void demo01(){
 applicationContext.getBean("accountService", AccountService.class);
        accountService.transfer("jack","rose",100);
    }
}

2.整合web

1.tomcat 启动加载配置文件

    servlet-->init(ServletConfig) --><Load-on-startup>2
    
    filter--> ServletContextListener --> servletContext 对象监听
    spring 提供监听器 ContextLoaderListener -->web.xml<listener><listener-class> ....
    如果只配置监听器,默认加载xml位置:/WEB-INF/applicationContext.xml
  1. 确定配置文件 文职,通过系统初始化参数
SercletContext 初始化参数web.xml
    <context-param>
    <param-name>contextConfigLocation
    <prarm-value>classpath:applicationContext.xml
 <!--确定配置文件位置-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    
    <!--配置spring 监听器 加载xml配置文件-->
    <listener>
        <listener-class>org.springframework.web.context.ContextCleanupListener</listener-class>
    </listener>

相关文章

  • 小案例-转账

    转账 1.1 搭建环境 创建表 1.2.1 Dao层 1.2.2 service层 1.2.3 spring配置文...

  • JDBC(四)事务管理

    1.银行转账案例 案例:银行转账:从张无忌账户上给赵敏转1000块钱.准备:account(账户表): 转账操作步...

  • Spring(三)事务

    Spring 事务 案例 转账案例 IAccountDao 接口 AccountDaoImpl 实现类 IAcco...

  • 只有银行转账记录,法院能认定借贷关系吗

    关于没有借条,只有银行转账凭证,法院能否认定借贷关系的问题,老规矩,我们还是以案例的形式来解答。 【案例简介】 小...

  • Spring(二):AOP 面向切面编程

    转账案例 需求:使用 spring 框架整合 DBUtils 技术,实现用户转账功能 基础功能 步骤分析: 创建 ...

  • Spring -- 手写 IOC 和 AOP

    一、银行转账案例 先使用原始 servlet 方式模拟一个银行转账的功能,关键代码如下: TransferServ...

  • 07.银行转账案例

    2.案例中添加转账方法并演示事务问题新建一个工程,仍然复制以前的代码在这个新工程中,现在是一个银行转账案例,需要添...

  • 并发场景下死锁

    案例场景 例如账户A 转账户B、账户C 转账户D这两个转账操作。 这种方式采用了细粒度锁。使用细粒度锁可以提高并行...

  • 《基本账户》转账案例分析

    案例1: 黄某在某市某商业银行开设的个人结算账户,在2015年5月1日至2017年5月1日期间共发生交易1904笔...

  • 分布式事务的一致性

    问题 举个转账的例子,小韩给小马转账100元,如何保证两者账户金额正确? 将转账的过程分成两步:1.小韩的账户扣减...

网友评论

      本文标题:小案例-转账

      本文链接:https://www.haomeiwen.com/subject/luwkgctx.html