zoukankan      html  css  js  c++  java
  • 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方法进行事务管理,同时也可在这注解后进行详细的注解

  • 相关阅读:
    分部视图
    linq的几个方法
    如何让服务器支持mp4文件下载和sqlserver将表生成为sql语句方法
    在asp.net mvc中导出Excel文件
    Linq2EF操作中的两个小问题
    JSON到底是什么?
    连接跟踪(conntrack):原理、应用及 Linux 内核实现 转载
    没有安全,没有隐私
    互联网发展到今天,我们要做的,是用机器解决人类解决不了的问题。在这个意义上,比起人工智能,机器智能这个词更加准确。
    今天,世界各国城市的可持续发展面临很大挑战,这些挑战也带来了一个难得的机遇,就是利用机器智能解决城市发展过程中许多重要的问题,如交通治理。同时这也是像机器智能这样的新一代技术快速发展的机遇,这正是我全身心推动城市大脑的原因
  • 原文地址:https://www.cnblogs.com/lzj-learn/p/12746413.html
Copyright © 2011-2022 走看看