java——Spring(4)

Spring事务管理

 

 

 

 

 

 

TransactionDefinition:

 

 

 

 

 

业务的传播行为:

 为的是解决业务层方法之间的相互调用问题(一个service层里的方法调用另一个service里中的方法,这两个service中又分属于两个不同的事务,传播行为就是为了解决方法调用时事务的传递)

 

 

业务:实现转账功能,需保证业务的事务性

构思:

业务层:继承一个Service接口,该接口实现转账方法;

Dao层:继承Dao接口,实现具体的转入和转出功能

Dao层的参数从Service实现类传入(转出、转入、转账值)

编程式的业务管理:

Service实现类:

package com.spring.demo1;

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

//转账案例实现类
public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
//注入事务管理模板
    private TransactionTemplate transactionTemplate;

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    public void transfer(final String out, final String in, final Double money) {
        // TODO Auto-generated method stub
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus arg0) {
                // TODO Auto-generated method stub
                accountDao.outMoney(out, money);
                accountDao.inMoney(in, money);
    
        }
        });

}
}

这里通过事务管理模板的注入,使用其内置方法对业务进行事务处理

Dao实现类:

package com.spring.demo1;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

//转账案例Dao的实现类
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

    @Override
    public void outMoney(String out, Double money) {
        // TODO Auto-generated method stub
        String sql = "update account set money = money - ? where name = ?";
        this.getJdbcTemplate().update(sql,money,out);
    }

    @Override
    public void inMoney(String in, Double money) {
        // TODO Auto-generated method stub
        String sql = "update account set money = money + ? where name = ?";
        this.getJdbcTemplate().update(sql,money,in);
    }

}

这里通过继承JdbcDaoSupport类,里面定义了一个dataSource参数,将实例化的连接池传入这个参数后即可连接到数据库;再调用getJdbcTemplate方法对sql语句进行执行操作;

相关的spring.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:c="http://www.springframework.org/schema/c"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <context:property-placeholder location = "classpath:jdbc.properties" />
    <!-- 配置连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!-- 在Dao层直接通过继承JdbcDaoSupport接口,在这实例化时对接口里定义好的参数:DataSource,进行注入连接池,使Dao层连接数据库成功 -->
    <bean id="accountDao" class="com.spring.demo1.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="accountService" class="com.spring.demo1.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
        <property name="transactionTemplate" ref="transactionTemplate"></property>
    </bean>
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 事务管理模板,简化管理代码 -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>
    
</beans>

运行类或测试类:

package com.spring.demo1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.demo2.AccountServiceImpl;

public class test01 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        AccountServiceImpl bean = context.getBean("accountService",AccountServiceImpl.class);
        bean.transfer("aaa", "bbb", 200.0);
        System.out.println("hahha");
    }

}

这种是通过先配置好连接数据库的配置文件,再配置连接池,进而配置事务管理器,形成对应的事务管理模板,在调用模板里的方法进行与数据库的交互;

 

 

 

 

声明式的业务管理器(一)<xml形式>:

这里的事务的实现更像是AOP那种,通过实例化一个代理类,在代理类中添加事务管理器,以及管理的事务属性:

业务Service实现类:

package com.spring.demo2;

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

//转账案例实现类
public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
//注入事务管理模板
    private TransactionTemplate transactionTemplate;

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    public void transfer(final String out, final String in, final Double money) {
        // TODO Auto-generated method stub
                accountDao.outMoney(out, money);
                //int i = 6/0;
                accountDao.inMoney(in, money);
    
        }
}

Dao实现类:

package com.spring.demo2;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

//转账案例Dao的实现类
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

    @Override
    public void outMoney(String out, Double money) {
        // TODO Auto-generated method stub
        String sql = "update account set money = money - ? where name = ?";
        this.getJdbcTemplate().update(sql,money,out);
    }

    @Override
    public void inMoney(String in, Double money) {
        // TODO Auto-generated method stub
        String sql = "update account set money = money + ? where name = ?";
        this.getJdbcTemplate().update(sql,money,in);
    }

}

Spring2.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:c="http://www.springframework.org/schema/c"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <context:property-placeholder location = "classpath:jdbc.properties" />
    <!-- 配置连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="${jdbc.driverClass}"></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="accountDao" class="com.spring.demo2.AccountDaoImpl">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="accountService" class="com.spring.demo2.AccountServiceImpl">
    	<property name="accountDao" ref="accountDao"></property>
    </bean>
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 配置业务层的代理 -->
    <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    	<property name="target" ref="accountService"></property>
    	<property name="transactionManager" ref="transactionManager"></property>
    	<property name="transactionAttributes">
    	<!-- 
    		prop的格式:
    		PROPAGATION:事务的传播行为
    		ISOLATION:事务的隔离级别
    		readOnly:只读
    		-Exception:发生哪些异常时回滚事务
    		+Exception:发生哪些异常时不回滚事务
    	 -->
    		<props>
    			<prop key="transfer">
    				PROPAGATION_REQUIRED
    			</prop>
    		</props>
    	</property>
    </bean>
</beans> 

  测试或运行类:

package com.spring.demo2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.demo2.AccountServiceImpl;

public class test01 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ApplicationContext context = new ClassPathXmlApplicationContext("spring2.xml");
        AccountService bean = (AccountService)context.getBean("accountServiceProxy");
        bean.transfer("aaa", "bbb", 200.0);
        System.out.println("hahha");
    }

}

这里需要实例化的时候不是原本的"accountService",而是"accountServiceProxy";

可对比编程式的事务管理,申明式的管理基本无需改动Servicr里的代码,主要是在Spring2.xml就可配置实现好事务管理功能了

 

 

 

声明式的业务管理器(二)<基于Asoectj>

对于Dao层和Service层无需做改变,对spring3.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:c="http://www.springframework.org/schema/c"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <context:property-placeholder location = "classpath:jdbc.properties" />
    <!-- 配置连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"></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="accountDao" class="com.spring.demo3.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="accountService" class="com.spring.demo3.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>
     <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 配置事务的通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- propagation:事务传播行为 
                isolation:事务隔离级别(DEFAULT表示按数据库的默认隔离级别)
            -->
            <tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
        </tx:attributes>
    </tx:advice>
    <!-- 配置切面 -->
    <aop:config>
        <aop:pointcut expression="execution(* com.spring.demo3.AccountService+.*(..))" id="pointcut1"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>    
    </aop:config>
</beans>

声明式的业务管理器(三)<基于注解的方式>

在spring4.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:c="http://www.springframework.org/schema/c"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <context:property-placeholder location = "classpath:jdbc.properties" />
    <!-- 配置连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"></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="accountDao" class="com.spring.demo4.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="accountService" class="com.spring.demo4.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>
     <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 开启注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
</beans>

 

在需要进行事务处理的业务层进行注解@Transactional(),对该类下的所有public方法进行事务管理,同时也可在这注解后进行详细的注解

posted @ 2020-04-26 14:01  xiao兆  阅读(178)  评论(0编辑  收藏  举报