A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 大蓝鲸小蟀锅 于 2017-12-27 15:09 编辑

Spring 事务管理的总结和入门案例演示Spring事务管理高层抽象主要包括3个接口
1.PlatformTransactionManager
        事务管理器
2.TransactionDefinition
        事务定义信息(隔离、传播、超时、只读)
3.TransactionStatus
        事务具体运行状态
事务管理器PlatformTransactionManage
Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现

事务隔离级别(种)如下:
脏读:一个事务读取了另个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。
不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是,后续读取不能读到另一事务已提交的更新数据。
幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录。
事务传播行为
事务传播行为用于解决两个被事务管理的方法互相调用问题
事务传播行为(七种)如下:
NESTED 嵌套事务示例如下:
Connection conn = null;
try {
    conn.setAutoCommit(false);
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("update person set name='888' where id=1");
    Savepoint savepoint = conn.setSavepoint();
    try{   
            conn.createStatement().executeUpdate("update person set name='222' where sid=2");
    }catch(Exception ex){
            conn.rollback(savepoint);   
     }
      stmt.executeUpdate("delete from person where id=9");
      conn.commit();
       stmt.close();
    } catch (Exception e) {
         conn.rollback();
     }finally{
               try {
            if(null!=conn && !conn.isClosed()) conn.close();
                } catch (SQLException e) { e.printStackTrace(); }
     }
}

Spring 事务管理
Spring 支持两种方式事务管理
编程式的事务管理
在实际应用中很少使用
通过TransactionTemplate手动管理事务
使用XML配置声明式事务
开发中推荐使用(代码侵入性最小)
Spring的声明式事务是通过AOP实现的

下面是代码<转账>案例演示:
1. 转账案例的环境准备
创建web工程
导入jar
src目录编写配置
applicationContext.xml        
log4j.properties
jdbc.properties

2. 编写DAO注入 注入JdbcTemplate
public class AccountDAO  extends JdbcDaoSupport{
        public void outMoney(String account, double money) {
            this.getJdbcTemplate().update(
                "update account set money = money - ? where name = ?", money,account);
        }
        public void inMoney(String account, double money) {
            this.getJdbcTemplate().update(
                "update account set money = money + ? where name = ?", money,account);
        }
}

编写Service注入DAO
public class AccountService {
        private AccountDAO accountDAO;
        // 转账的业务操作
        public void transfer() {
                // aaa bbb 转账 200
                accountDAO.outMoney("aaa", 200);
                int d = 1 / 0;
                accountDAO.inMoney("bbb", 200);
        }
        public void setAccountDAO(AccountDAO accountDAO) {
                this.accountDAO = accountDAO;
        }
配置applicationContext.xml
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <!-- ${key} 可以读取properties文件中配置 key对应value -->
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="accountService" class="cn.itcast.service.AccountService">
        <property name="accountDAO" ref="accountDAO"></property>
</bean>
<bean id="accountDAO" class="cn.itcast.dao.AccountDAO">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
编写测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringTest {
        @Autowired
        private AccountService accountService;
        @Test
        public void demo() {
                accountService.transfer();
        }
}
使用XML配置声明式事务 基于tx/aop


<tx:method>配置
使用XML配置声明式事务 基于tx/aop
修改测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringTest {
        @Autowired
        private AccountService accountService;
        @Test
        public void demo() {
                accountService.transfer();
        }
}
使用注解配置声明式事务
使用@Transactional注解 修改AccountService
@Transactional
public class AccountService {
        private AccountDAO accountDAO;
        // 转账的业务操作
        public void transfer() {
                // aaa bbb 转账 200
                accountDAO.outMoney("aaa", 200);
                // int d = 1 / 0;
                accountDAO.inMoney("bbb", 200);
        }
        public void setAccountDAO(AccountDAO accountDAO) {
                this.accountDAO = accountDAO;
        }
}
使用注解配置声明式事务
修改applicationContext.xml
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <!-- ${key} 可以读取properties文件中配置 key对应value -->
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
</bean>
...
<tx:annotation-driven/>


评分

参与人数 1黑马币 +5 收起 理由
@狂奔 + 5 赞一个!

查看全部评分

1 个回复

倒序浏览
郭俊峰老师 来自手机 高级黑马 2017-12-27 15:13:20
沙发
好贴一定要顶!!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马