小案例-转账

转账

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>
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 原文链接:https://docs.spring.io/spring-boot/docs/1.4.x/refere...
    pseudo_niaonao阅读 4,930评论 0赞 9
  • IOC和DI是什么? Spring IOC 的理解,其初始化过程? BeanFactory 和 FactoryBe...
    justlpf阅读 3,635评论 1赞 21
  • Spring 复习 [toc] spring介绍 三层架构中spring位置,连接三层。 spring一站式框架正...
    inke阅读 893评论 0赞 11
  • 这部分的参考文档涉及数据访问和数据访问层和业务或服务层之间的交互。 Spring的综合事务管理支持覆盖很多细节,然...
    竹天亮阅读 1,120评论 0赞 0
  • 今天早上到公司,可能是因为假期综合征,不是很想看书,然后就想到了坚持这个词。坚持,是一个老掉牙的话题了,但是依然是...
    LY丶Smile阅读 212评论 0赞 2

友情链接更多精彩内容