spring事务管理

零售-公司间关联交易退货STO的实现方式 零售-公司间关联交易采购 STO-退货 集团公司下经常会出现一家公司和另外一家公司的公司间的关联交易,如跨公司销售、总分公司之间采购,分公司之间的采购等业务;通常公司间采购会采取STO的模式来实现(根据业务模式可以将库存转储统一做成STO的模式,公司间STO、同公司工厂间、同工厂库存地点间 的STO SAP都是支持的); 公司间STO 正向A向B采购都很熟悉,公司间退货STO的其实也是比较普遍的业务现象,很多实施着也将其做成反向的STO(B向A采购),而不是退货STO(A向B,item 选择return的标 阅读详情

我们都知道spring提供两种管理事务的方式,一种是声明式事务,一种是编程式事务。
Spring的声明式事务管理,基于Spring的AOP,不再需要不停地写commit,rollback,(但Spring仍然没有放弃编程式的事务管理策略)。
Spring的编程式事务管理,为我们提供了一个TransactionTemplate,使用回调机制,将应用代码从样板式的资源获取和释放代码中解放出来,不再有大量的try/catch/finally/try/catch代码块。

 

这两种事务处理方式都非常地优雅,它不需要与任何特定的事务API耦合,并支持多种持久层方案。
(1)声明式事务:基于Spring AOP实现,几乎就是xml文件的配置
(2)编程式事务:统一的事务编码风格,几乎是一个模板化的。

 

以下将对这两种事务管理方式进行探讨:

首先探讨一下声明式事务:
我们知道Spring事务管理的核心接口是:
org.springframework.transaction.PlatformTransactionManager
它定义了三个待实现的方法:
(1)public TransactionStatus getTransaction(TransactionDefinition definition);
 //返回当前活动的事务或根据相应的行为创建一个新的事务(可以查阅API理解)
(2)public void commit(TransactionStatus status);//提交事务
(3)public void rollback(TransactionStatus status); //回滚事务

PlatformTransactionManager是一个与特定平台无关的事务操作接口,不同的底层事务平台应通过Spring的Ioc注入相应的事务操作实现类 (这些实现类也不需要我们去完成,Spring已经为我们提供了)。那么我们来看看针对不同的底层持久化平台,我们需要为PlatformTransactionManager接口注入何种实现类:

Xml代码
  1. (1)利用JDBC作为持久层的局部事务:   
  2. <?xml version="1.0" encoding="utf-8"?>  
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans    
  6.        http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.   
  8. <!-- 定义数据源Bean,使用C3P0数据源 -->  
  9. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy- method="close">  
  10.     <!-- 指定连接数据库的驱动 -->  
  11.     <property name="driverClass" value="com.mysql.jdbc.Driver"/>  
  12.     <!-- 指定连接数据库的URL -->  
  13.     <property name="jdbcUrl" value="jdbc:mysql:3306//127.0.0.1/ssh"/>  
  14.     <!-- 指定连接数据库的用户名 -->  
  15.     <property name="user" value="root"/>  
  16.     <!-- 指定连接数据库的密码 -->  
  17.     <property name="password" value="123"/>  
  18.     <!-- 指定连接数据库连接池的最大连接数 -->  
  19.     <property name="maxPoolSize" value="40"/>  
  20.     <!-- 指定连接数据库连接池的最小连接数 -->  
  21.     <property name="minPoolSize" value="1"/>  
  22.     <!-- 指定连接数据库连接池的初始化连接数 -->  
  23.     <property name="initialPoolSize" value="1"/>  
  24.     <!-- 指定连接数据库连接池的连接最大空闲时间 -->  
  25.     <property name="maxIdleTime" value="20"/>  
  26. </bean>  
  27.   
  28. <!—定义JDBC数据源的局部事务管理器 -->  
  29. <!-- 使用DataSourceTransactionManager类,该类实现PlatformTransactionManager接口 ,是针对采用数据源连接的特定实现 -->  
  30. <bean id="transactionManager"    
  31.         class="org.springframework.jdbc.datasource.   
  32.         DataSourceTransactionManager">  
  33.         <!—DataSourceTransactionManager需要注入一个DataSource的引用-->  
  34.          <property name="dataSource" ref="dataSource"/>  
  35.     </bean>  
  36. </beans>  
  37.   
  38. (2)利用Hibernate作为持久层的局部事务:   
  39. <?xml version="1.0" encoding="utf-8"?>  
  40. <beans xmlns="http://www.springframework.org/schema/beans"  
  41.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  42.        xsi:schemaLocation="http://www.springframework.org/schema/beans    
  43.        http://www.springframework.org/schema/beans/spring-beans.xsd">  
  44.     <!-- 定义数据源Bean,使用C3P0数据源 -->  
  45.     <bean id="dataSource" class="com.mchange.v2.c3p0.    
  46.     ComboPooledDataSource" destroy-method="close">  
  47.         <!-- 指定连接数据库的驱动 -->  
  48.         <property name="driverClass" value="com.mysql.jdbc.Driver"/>  
  49.         <!-- 指定连接数据库的URL -->  
  50.         <property name="jdbcUrl" value="jdbc:mysql:3306//127.0.0.1/ssh"/>  
  51.         <!-- 指定连接数据库的用户名 -->  
  52.         <property name="user" value="root"/>  
  53.         <!-- 指定连接数据库的密码 -->  
  54.         <property name="password" value="123"/>  
  55.         <!-- 指定连接数据库连接池的最大连接数 -->  
  56.         <property name="maxPoolSize" value="40"/>  
  57.         <!-- 指定连接数据库连接池的最小连接数 -->  
  58.         <property name="minPoolSize" value="1"/>  
  59.         <!-- 指定连接数据库连接池的初始化连接数 -->  
  60.         <property name="initialPoolSize" value="1"/>  
  61.         <!-- 指定连接数据库连接池的连接最大空闲时间 -->  
  62.         <property name="maxIdleTime" value="20"/>  
  63.     </bean>  
  64.   
  65.     <!-- 定义Hibernate的SessionFactory -->  
  66.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.    
  67.     LocalSessionFactoryBean">  
  68.         <!-- 注入SessionFactory所需的数据源 -->  
  69.         <property name="dataSource" ref="dataSource"/>  
  70.         <!--列出全部映射文件 -->  
  71.         <property name="mappingResources">  
  72.               <list>  
  73.                   <!--列出所有的PO映射文件 -->  
  74.                 <value>org/hnylj/vo/User.hbm.xml</value>  
  75.               </list>  
  76.         </property>  
  77.           <!-- 定义Hibernate的SessionFactory属性 -->  
  78.         <property name="hibernateProperties">  
  79.             <props>  
  80.                 <!-- 指定Hibernate的连接方言 -->  
  81.                 <prop key="hibernate.dialect">org.hibernate.dialect.    
  82.                 MySQLDialect</prop>  
  83.         </property>  
  84.     </bean>  
  85.   
  86.     <!-- 配置Hibernate的局部事务管理器 -->  
  87.     <!-- 使用HibernateTransactionManager类,该类实现PlatformTransactionManager   
  88.     接口,是针对采用Hibernate持久化连接的特定实现 -->  
  89.     <bean id="transactionManager"    
  90.       class="org.springframework.orm.hibernate3.    
  91.       HibernateTransactionManager">  
  92.             <!--注入一个SessionFactorybean的引用 -->  
  93.          <property name="sessionFactory" ref="sessionFactory"/>  
  94.      </bean>  
  95. </beans>  
  96.   
  97. (3)利用Hibernate作为持久层的全局事务:   
  98. <?xml version="1.0" encoding="utf-8"?>  
  99. <beans xmlns="http://www.springframework.org/schema/beans"  
  100.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  101.        xsi:schemaLocation="http://www.springframework.org/schema/beans    
  102.        http://www.springframework.org/schema/beans/spring-beans.xsd">  
  103.     <!—定义JNDI数据源Bean -->  
  104.     <bean id="dataSource" class="org.springframework.jndi.    
  105.     JndiObjectFactoryBean">  
  106.         <!--  容器管理数据源的JNDI -->  
  107.          <property name="jndiName" value="jdbc/jtest"/>  
  108.     </bean>  
  109.     <!--定义Hibernate的SessionFactory -->  
  110.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.    
  111.     LocalSessionFactoryBean">  
  112.         <!-- 注入SessionFactory所需的数据源-->  
  113.         <property name="dataSource" ref="dataSource"/>  
  114.         <!--列出全部映射文件 -->  
  115.         <property name="mappingResources">  
  116.               <list>  
  117.                   <!-- 列出所有的PO映射文件 -->  
  118.                 <value>org/hnylj/vo/User.hbm.xml</value>  
  119.               </list>  
  120.         </property>  
  121.           <!-- 定义Hibernate的SessionFactory的属性 -->  
  122.         <property name="hibernateProperties">  
  123.              <props>  
  124.                 <!-- 指定Hibernate的连接方言 -->  
  125.                 <prop key="hibernate.dialect">org.hibernate.dialect.    
  126.                 MySQLDialect</prop>  
  127.          </property>  
  128.     </bean>  
  129.     <!-- 使用JtaTransactionManager类,该类实现PlatformTransactionManager接口-->  
  130.     <!-- JtaTransactionManager不需要知道数据源,或任何其他特定资源,   
  131.             因为使用容器的全局事务管理 -->  
  132.     <bean id="transactionManager"    
  133.            class="org.springframework.transaction.jta.   
  134.            JtaTransactionManager" />  
  135. </beans>  

在上面的配置中,对于采用jdbc,hibernate等,我们只要提供相应的PlatformTransactionManager实现类即可。可见Spring对事务的操作仅仅修改一下配置文件,不需要修改任何实际的代码,就可以在不同的事务管理策略之间切换,非常地方便,Spring为我们提供了高度的解耦。

 

以上就是我们在spring中处理事务所需要的事务管理器的配置,那么在具体的业务处理bean中我们如何控制事务呢?
一般都推荐事务最好做在service层,底层的dao可以不考虑事务,有时设计得不好可能会出现事务的嵌套,增加程序复杂度。而且将事务的处理放在service层中进行,对于我们异常体系的设计也带来好处,service层抛出的异常可以在web捕获,并将异常信息在web页面给用户提示。所以接下来我们就将在service层开始事务,提交事务,回滚事务等。作为声明式事务管理,spring已经帮我们做好了这一切,基本上就是代理模式。

 

以下就是Spring提供的4种事务代理方式:
1.使用TransactionProxyFactoryBean为目标bean生成事务代理,此方式是最传统,也是配置文件最臃肿的一种方式。
2.使用bean继承的事务代理方式,此方式比较简洁,但依然是增量式配置,bean越多配置文件越臃肿。
3.使用BeanNameAutoProxyCreator,根据bean name自动生成事务代理的方式,这是直接利用Spring的AOP框架配置事务代理的方式,需要对Spring的AOP框架有所了解,但也不必成为AOP专家,这种方式避免了增量式配置,也是推荐的方式。
4.使用DefaultAdvisorAutoProxyCreator,这也是直接利用Spring的AOP框架配置事务代理的方式,只是这种配置方式的可读性不如第三种方式。

 

对于第一种:使用TransactionProxyFactoryBean为目标bean生成事务代理:
因为TransactionProxyFactoryBean产生的是代理Bean,所以我们在配置TransactionProxyFactoryBean时,需要指定目标Bean。每个TransactionProxyFactoryBean为一个目标Bean生成事务代理,事务代理的方法改写了目标Bean的方法,就是在目标Bean的方法执行之前加入开始事务,在目标Bean的方法正常结束之前提交事务,如果遇到特定异常则回滚事务。TransactionProxyFactoryBean创建事务代理时,需要了解当前事务所处的环境,该环境属性通过PlatformTransactionManager实例传入,而相关事务传入规则在TransactionProxyFactoryBean的定义中给出。

下面该方法的配置方式:

Xml代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans    
  5.        http://www.springframework.org/schema/beans/spring-beans.xsd">  
  6.     <!-- 定义数据源Bean,使用C3P0数据源 -->  
  7.     <bean id="dataSource" class="com.mchange.v2.c3p0.    
  8.     ComboPooledDataSource" destroy-method="close">  
  9.         <!-- 指定连接数据库的驱动 -->  
  10.         <property name="driverClass" value="com.mysql.jdbc.Driver"/>  
  11.         <!-- 指定连接数据库的URL -->  
  12.         <property name="jdbcUrl" value="jdbc:mysql:3306//127.0.0.1/ssh"/>  
  13.         <!-- 指定连接数据库的用户名 -->  
  14.         <property name="user" value="root"/>  
  15.         <!-- 指定连接数据库的密码 -->  
  16.         <property name="password" value="123"/>  
  17.         <!-- 指定连接数据库连接池的最大连接数 -->  
  18.         <property name="maxPoolSize" value="40"/>  
  19.         <!-- 指定连接数据库连接池的最小连接数 -->  
  20.         <property name="minPoolSize" value="1"/>  
  21.         <!-- 指定连接数据库连接池的初始化连接数 -->  
  22.         <property name="initialPoolSize" value="1"/>  
  23.         <!-- 指定连接数据库连接池的连接最大空闲时间 -->  
  24.         <property name="maxIdleTime" value="20"/>  
  25.     </bean>  
  26.   
  27.     <!-- 定义Hibernate的SessionFactory -->  
  28.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.    
  29.     LocalSessionFactoryBean">  
  30.         <!-- 注入SessionFactory所需的数据源-->  
  31.         <property name="dataSource" <refref="dataSource"/>  
  32.         <!--列出全部映射文件 -->  
  33.         <property name="mappingResources">  
  34.               <list>  
  35.                   <!--列出所有的PO映射文件 -->  
  36.                 <value>org/hnylj/vo/User.hbm.xml</value>  
  37.               </list>  
  38.         </property>  
  39.           <!-- 定义Hibernate的SessionFactory属性 -->  
  40.         <property name="hibernateProperties">  
  41.              <props>  
  42.                 <!-- 指定Hibernate的连接方言 -->  
  43.                 <prop key="hibernate.dialect">org.hibernate.dialect.    
  44.                 MySQLDialect</prop>  
  45.              </props>  
  46.         </property>  
  47. </bean>  
  48. <!-- 配置DAO Bean -->  
  49.     <bean id="userDAO" class="org.hnylj.dao.impl.UserDaoImpl">     
  50.         <property name="sessionFactory">     
  51.             <ref bean="sessionFactory" />     
  52.         </property>     
  53.     </bean>     
  54.   
  55.     <!-- 配置Service Bean,该Bean将作为目标Bean使用 -->  
  56.     <bean id="userServiceTarget" class="org.hnylj.service.impl.UserServiceImpl">  
  57.         <!-- 依赖注入userDAO的引用 -->  
  58.         <property name="userDAO" ref="userDAO"/>  
  59.     </bean>  
  60.   
  61.     <!-- 配置Hibernate的事务管理器 -->  
  62.     <!-- 使用HibernateTransactionManager类,该类实现PlatformTransactionManager   
  63.     接口,针对采用Hibernate持久化连接的特定实现 -->  
  64.     <bean id="transactionManager"    
  65.         class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  66.         <!-- HibernateTransactionManager Bean,它需要依赖注入一个SessionFactory   
  67.         Bean的引用 -->  
  68.         <property name="sessionFactory" ref="sessionFactory"/>  
  69.     </bean>  
  70.   
  71.     <!--  配置userServiceTarget Bean的事务代理 -->  
  72.     <bean id="userService"    
  73.         class="org.springframework.transaction.interceptor.    
  74.         TransactionProxyFactoryBean">  
  75.           <!-- 依赖注入PlatformTransactionManager的bean引用,此处使用   
  76.           Hibernate的bean -->  
  77.           <!-- 局部事务器,传入Hibernate事务管理器的引用 -->  
  78.           <property name="transactionManager" ref="transactionManager"/>  
  79.           <!-- 需要生成代理的目标bean -->  
  80.           <property name="target" ref="userServiceTarget"/>  
  81.           <!-- 指定事务属性 -->  
  82.           <property name="transactionAttributes">  
  83.               <props>  
  84.                   <!-- 以下部分为定义事务回滚规则 -->  
  85.                   <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop>  
  86.                   <prop key="update*">PROPAGATION_REQUIRED</prop>  
  87.                   <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>  
  88.               </props>  
  89.         </property>  
  90.     </bean>  
  91. </beans>  

关于以上配置文件的几个事务传播规则可以查阅相应的API

程序面向UserServiceImpl类所实现的接口编程,事务处理由Spring为UserServiceImpl类所实现的接口IUserService生成的代理bean来完成。(Spring不仅支持对接口的代理,Spring结合CGLIB还可以为具体类生成代理,在此不做讨论)

 

对于第二种:采用bean继承的事务代理
仔细观察第一种配置方式,我们可以发现,如果配置文件中有多个这样的事务代理Bean,配置文件将变得非常臃肿。所以可以使用Bean继承来简化事务代理的配置。考虑到所有事务代理Bean中,事务代理Bean所使用的事务管理器和事务传播规则大致是相同的,所以我们可以定义一个事务代理bean的模板。
即:

Xml代码
  1. <!-- 定义所有事务代理Bean的模板 -->  
  2. <bean id="txProxyTemplate" abstract="true"  
  3.         class="org.springframework.transaction.interceptor.   
  4.         TransactionProxyFactoryBean">  
  5.     <!-- 为事务代理Bean注入生成代理所需的PlatformTransactionManager实例 -->  
  6.     <property name="transactionManager" ref="transactionManager"/>  
  7.         <!-- 定义生成事务代理通用的事务属性 -->  
  8.         <property name="transactionAttributes">  
  9.             <props>  
  10.                 <!-- 所有的方法都应用PROPAGATION_REQUIRED的事务传播规则 -->  
  11.                 <prop key="*">PROPAGATION_REQUIRED</prop>  
  12.             </props>  
  13.     </property>  
  14. </bean>   

接下来让真正的事务代理Bean继承上面的事务模板Bean

Xml代码
  1. <!-- 让事务代理Bean继承模板Bean -->  
  2. <bean id="userService" parent="txProxyTemplate">  
  3.     <!-- 这里是嵌套Bean的配置方式 -->  
  4.     <property name="target">  
  5.         <bean class="org.hnylj.service.impl.userServiceImpl"/>  
  6.     </property>  
  7. </bean>  

我们知道,继承中子类可以复写父类的方法,这里也一样,子Bean重新定义事务属性将覆盖事务代理模板里的事务属性定义:
即:

Xml代码 <!-- 让事务代理bean继承模板Bean -->  
  1. <bean id="userService" parent="txProxyTemplate">  
  2.     <!-- 这里引用已存在的bean的方式来定义目标Bean -->  
  3.     <property name="target" ref ="userServiceTarget"/>  
  4.     <!-- 覆盖事务代理模板bean中的事务属性定义 -->  
  5.     <property name="transactionAttributes">  
  6.         <props>  
  7.             <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>  
  8.             <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>  
  9.             <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>  
  10.          </props>  
  11.     </property>  
  12. </bean>  

可见,采用Bean继承方式定义事务代理的方式,可以很好地简化事务代理的配置,可以避免配置事务代理Bean时的冗余配置。

 

对于第三种:使用BeanNameAutoProxyCreator
使用BeanNameAutoProxyCreator来创建代理时,并不一定是创建事务代理,关键在于传入的拦截器,如果传入事务拦截器,将可自动生成事务代理。

下面是使用BeanNameAutoProxyCreator自动生成事务代理的配置方式:

如果配置文件中仅有两个目标Bean,可能不能很清楚地看出这种自动创建代理配置方式的优势,但如果有更多目标Bean需要自动创建事务代理,则可以很好地体会到这种配置方式的优势:配置文件只需要简单地配置目标Bean,然后在BeanNameAutoProxyCreator配置中增加一行即可。

 

对于第四种:DefaultAdvisorAutoProxyCreator:
这种配置方式与BeanNameAutoProxyCreator自动创建代理的方式非常相似,都是使用bean后处理器为目标bean生成事务代理,区别是前者使用事务拦截器创建代理,后者需要使用Advisor创建事务代理。事实上,采用DefaultAdvisorAutoProxyCreator的事务代理配置方式更加简洁,这个代理生成器自动搜索Spring容器中的Advisor,并为容器中所有的bean创建代理。相对前一种方式,这种方式的可读性不如前一种直观。
使用DefaultAdvisorAutoProxyCreator的配置方式:

<?xml version="1.0" encoding="utf-8"?>
<!-- 指定Spring配置文件的根元素,以及相应的Schema信息 -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义数据源Bean,使用C3P0数据源实现 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0. 
    ComboPooledDataSource" destroy-method="close">
        <!-- 指定连接数据库的驱动 -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <!-- 指定连接数据库的URL -->
        <property name="jdbcUrl" value="jdbc:mysql:3306/127.0.0.1/ssh"/>
        <!-- 指定连接数据库的用户名 -->
        <property name="user" value="root"/>
        <!-- 指定连接数据库的密码 -->
        <property name="password" value="123"/>
        <!-- 指定连接数据库连接池的最大连接数 -->
        <property name="maxPoolSize" value="40"/>
        <!-- 指定连接数据库连接池的最小连接数 -->
        <property name="minPoolSize" value="1"/>
        <!-- 指定连接数据库连接池的初始化连接数 -->
        <property name="initialPoolSize" value="1"/>
        <!-- 指定连接数据库连接池的连接最大空闲时间 -->
        <property name="maxIdleTime" value="20"/>
    </bean>
    <!--定义一个hibernate的SessionFactory-->
<bean id="sessionFactory"  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <!--   定义SessionFactory必须注入DataSource-->
            <property name="dataSource"><ref local="dataSource"/></property>
            <property name="mappingResources">
            <list>
                <!--列出所有的PO映射文件-->
                <value>org/hnylj/vo/User.hbm.xml</value>
            </list>
            </property>
            <property name="hibernateProperties">
            <props>
<!--定义hibernate的SessionFactory的属性-->
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            </props>
        </property>
    </bean>
    <!-- 定义hibernate的局部事务管理器-->
<bean id="transactionManager"
         class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <!-- 注入SessionFactory bean的引用-->
            <property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
    <!--   配置事务拦截器-->
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <!--   事务拦截器bean需要依赖注入一个事务管理器 -->
        <property name="transactionManager" ref="transactionManager"/>
        <property name="transactionAttributes">
            <!--   下面定义事务传播属性-->
            <props>
                <prop key="insert*">PROPAGATION_REQUIRED</prop>
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
</bean>
    <!-- 定义事务Advisor-->
<bean  class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
        <!--   定义advisor时,必须传入Interceptor-->
            <property name="transactionInterceptor" ref="transactionInterceptor"/>
    </bean>
    <!-- DefaultAdvisorAutoProxyCreator搜索容器中的 advisor,并为每个bean创建代理 -->
<bean  class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<!--定义DAO Bean ,由BeanNameAutoProxyCreator自动生成事务代理-->
    <bean id="userService" class="org.hnylj.service.impl.UserServiceImpl">
        <property name="userDAO"><ref local="userDAO"/></property>
</bean>
</beans>  
Sigrity Power DC Resitance Network Model Generation模式生成电阻SPICE模型操作指导 Sigrity Power DC Resitance Network Model Generation模式是用于提取负载每个pin电阻SPICE模型的,结果以spice网表形式展现,仍然以Motherboard.spd为例进行说明。目的是模拟实际情况,via的孔壁电镀1mil,中间是空心的,让via不完全被填充金属成为实心via。Upper/lower Tolerance:上下公差,设置为5%,也就是压降允许的范围。P/F Mode:通过/失败模式,选择Worst,最差的情况。 阅读详情

相关推荐

六轴机器人正解

采用的是John H.Craig在【机器人学导论】中的改进DH模型 1.六轴坐标系 2.DH参数 i αi−1\alpha_{i-1}αi−1​ ai−1a_{i-1}ai−1​ did_idi​ θi\theta_iθi​初值 1 0 0 0 0 2 -90 a1a_1a1​ 0 -90 3 0 a2a_2a2​ 0 -90 4 -90 a3a_3a3​ d4d...

m0_37581770的博客 2511

Spring事务管理的那些事儿(上)

写在前面的话:本人开发过一个系统,系统对数据的正确性要求比较高,有个小模块中一次性会向数据库插入1万条左右的数据,在插入这一万条左右的数据的同时还要更新数据库中与此1万条数据相同的数据的某个状态值,更新出错或插入出错,都要回滚并终止执行。这就是一个典型的事务处理问题。   很早就接触到了Spring,通过时间的推移和实际项目的运用,对Spring的认识也渐渐增多,有了一些体会和感悟。 下面...

JavaKeeper 481

SAP S/4HANA 可扩展性 – 面向初学者的简化指南

可扩展性(Extensibility)是 SAP ECC 和 SAP S/4HANA 的一项关键功能。它使客户能够通过定制其业务流程来创造竞争优势,并使合作伙伴能够通过量身定制的解决方案来丰富核心 ECC 或 S/4HANA。在过去的几十年中,SAP 的 on-premise 版本客户和合作伙伴主要使用经典的 ABAP 扩展性来扩展他们的 ERP 解决方案。经典扩展性允许 ABAP 开发人员使用甚至修改所有 SAP 对象。尽管经典扩展性非常强大和灵活,但在当今的云世界中,它已不再是一个好的选择。

SAP学习成长之路的博客 1809

Spring事务

某些异常默认不会参与回滚,因此当出现这样的异常时,也会出现不同步的问题(即使开启了事务),因此对于特定的一些异常需要在注解中增加roolback=异常.class,才能实现事务正常。可以看出,现在我们需要LogService中的方法,不在事务T之中,它在独立的一个事务中。在注解@Transactional(roolback=xxx.class)但此时,这三个数据层的方法处于同一个事务,同成功同失败,不符合需求。增加了一个LogService。...

weixin_42196338的博客 376

SAP PS项目计划成本与预算设计:从概念到可用性控制详解

在项目管理中,成本计划与预算管控是决定项目成本能否受控的两个核心概念。成本计划反映“预计花费”,预算是“授权上限”,两者在WBS结构上既相互关联又彼此独立。SAP PS通过计划版本管理不同口径的估算,并借助可用性控制机制对采购申请、采购订单等业务操作进行事前拦截与提示,从而实现从“事后追认”到“事前控制”的转变。理解计划成本作为预算基线、预算作为控制阀门的原理,能够帮助实施顾问和项目管理者合理设计项目财务流程。在大型工程、研发或总包项目中,明确WBS层级、预算对象和检查规则,可有效避免超支风险。围绕SAP

weixin_33146151的博客 359

19、多项式基算术:原理与运算详解

本文深入探讨了有限域 $GF(2^m)$ 中的多项式基算术,详细介绍了加法、减法、乘法和平方运算的原理与实现方法。重点分析了多项式基表示形式、模约简技术以及乘法优化策略,如高基数乘法、并行与顺序乘法器设计,并提到了Karatsuba-Ofman算法在减少乘法次数方面的优势。此外,文章还讨论了多项式基算术在密码学、编码理论等领域的应用前景,并展望了未来在高效算法设计与硬件加速方面的研究方向。

yellow的专栏 150

【web】Spring中使用DataSourceTransactionManager手动提交或回滚事务

在使用spring进行web开发时,虽然spring提供的注解方式可以方便的处理很多原来需要手动提交或回滚的事务,但是注解方式有自己使用的局限,比如在类的内部调用方法时,注解方式处理的事务就无法被触发,此时可能需要手动处理相关数据库的事务。本文记录在spring开发时使用Spring提供的DataSourceTransactionManager进行事务提交或回滚处理。主要步骤如下: 1、注入Da

三言两语 1万+

在RV1126上实现人脸识别----MobileFaceNet转成rknn模型

目录 1.模型下载 2 转成rknn模型并推理 3 查看网络模型 1.模型下载 首先下载MobileFaceNet的模型,github下载地址为:https://github.com/sirius-ai/MobileFaceNet_TF/tree/master/arch/pretrained_model/ 2 转成rknn模型并推理 import numpy as np import cv2 from rknn.api import RKNN if __name__ == '__..

C/C++、嵌入式开发、深度学习算法、模型部署与推理优化 3526

Spring中使用DataSourceTransactionManager手动提交或回滚事务

      在使用spring进行web开发时,虽然spring提供的注解方式可以方便的处理很多原来需要手动提交或回滚的事务,但是注解方式有自己使用的局限,比如在类的内部调用方法时,注解方式处理的事务就无法被触发,此时可能需要手动处理相关数据库的事务。本文记录在spring开发时使用Spring提供的DataSourceTransactionManager进行事务提交或回滚处理。主要步骤如下:1、...

yxhxj2006的专栏 1万+

【MATLAB】嵌入式ADC/DAC控制工程

摘要:本文针对嵌入式ADC/DAC应用中存在的量化误差、采样噪声、输出漂移等问题,提出基于MATLAB的仿真优化方案。通过构建完整的ADC/DAC仿真模型,实现了采样建模、数字滤波、误差校准和闭环控制仿真。方案采用滑动平均滤波抑制ADC噪声,双校准参数补偿DAC固有误差,并将算法轻量化移植至STM32平台。实测表明,该方案使ADC采样波动从±25mV降至±5mV,DAC输出偏差从42mV降至18mV,显著提升了模拟量交互精度和系统稳定性。整套方案资源占用低,适配各类嵌入式高精度控制场景,具有较高的工程应用价

unber的博客 649

白话FOC控制中各环节的参数的意义与如何设置参数

FOC参数整定是控制系统的关键环节,如同驯马需要调节"智能马鞍"。核心参数分为三类:电流环参数(P/I/D)决定响应速度和稳定性,速度环参数需慢于电流环5-10倍带宽,系统参数(极对数、电阻等)是电机固有属性必须准确设置。调参心法:由内而外先调电流环,遵循先P后I慎用D原则,内环带宽必须大于外环。利用自动辨识工具,通过听觉(滋滋声表示P过大)和波形观察来微调,最终实现精准控制。

汽车软件开发 356

【Spring笔记-7】-spring完全注解开发实现事务管理

spring完全注解开发实现事务管理以及@Transactional中的参数

m0_64337991的博客 1137

外骨骼机器人(五):步态分析之正常步态

研究病理步态之前,需要了解正常步态,作为判断标准。但是需要记住两个问题:1.“正常”因人而异,性别、年龄、身体情况都需要考虑在内,因此,需要对不同的个体选择合适的正常标准;2.即使病人的步态与正常步态有某种不同,这也不能说明这是不可取的,也不能说明应该把它变成“正常”步态。许多步态异常是对病人的一些问题的一种补偿,尽管异常,但它们仍然是有用的。步态周期的定义是连续为两次发生重复行走事件之间的时间间隔。尽管可以选择任何事件来定义步态周期,但通常使用一只脚接触地面的瞬间(“初始接触”)是方便的。

行者无疆的博客 1995

【Spring】Spring的事务管理

该接口是Spring提供平台事务管理器,主要用于管理事务状态事务TransactionStatus getTransaction(TransactionDefinition definition):获取事务的状态信息void commit(TransactionStatus status):用于提交事务void rollback(TransactionStatus status):用于回滚事务该接口并不了解具体实现类,常用如下。

m0_62645012的博客 2068

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

【Spring】— Spring的事务管理

Spring的事务管理简化了传统的事务管理流程,并且在一定程度上减少了开发者的工作量。

衍生星球的博客 3320

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Spring事务管理总结

Spring事务管理机制概述 Spring事务管理模块主要包括3个接口 PlatformTransactionManager:事务管理器,主要用于平台相关的事务管理。 TransactionDefinition:事务定义信息(隔离级别、传播、超时、只读)通过配置如何进行事务管理。 TransactionStatus:事务具体运行状态——事务管理过程中,每个时间点事务的状态信息。 1、Platf...

qq_42961888的博客 695

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Spring:Spring事务管理知识讲解

Spring为了管理事务,提供了一个平台事务管理器commit是用来提交事务,rollback是用来回滚事务。PlatformTransactionManager只是一个接口,Spring还为其提供了一个具体的实现:从名称上可以看出,我们只需要给它一个DataSource对象,它就可以帮你去在业务层管理事务。其内部采用的是JDBC的事务。所以说如果你持久层采用的是JDBC相关的技术,就可以采用这个事务管理器来管理你的事务。

qq_41187116的博客 1407

Spring事务管理

介绍了事务的概念,事务的特性,JDBC 事务管理的步骤和操作过程,以及Spring事务管理的两种实现方式:编程式事务管理和声明式事务管理。

m0_74808313的博客 1277

【Spring】Spring事务管理

1.1简介Spring框架内部使用事务管理器的接口,来完成commit和rollback针对不同的框架,提供不同的实现类1.2ACID属性。

wosixiaokeai的博客 1145

Spring事务管理详解

Spring事务管理详解

一个普本码农奋斗史 8万+

Spring 事务管理机制概述

用户的每次请求都对应一个业务逻辑方法,而一个业务逻辑方法往往包括一系列数据库原子访问操作,并且这些操作应绑定成一个事务来执行。使用传统事务编程策略时,程序代码必然和具体的事务操作代码耦合,而Spring事务管理策略可以避免这种尴尬。Spring提供了两种事务管理方式:编程式事务管理和声明式事务管理,本文在对Spring事务管理API分析的基础上,详细地阐述了Spring编程式事务管理和声明式事务管理的原理、本质和使用

Rico's Blogs 3万+

说说Spring事务管理

实现了业务逻辑与事务控制的解耦。Spring 事务管理是 Spring 框架的核心功能之一,旨在简化数据库操作的原子性、一致性、隔离性和持久性(ACID)控制。原理:基于 AOP 动态代理,在运行时拦截@Transactional注解的方法,自动管理事务的开启、提交和回滚。嵌套事务回滚:REQUIRES_NEW的内层事务回滚不影响外层,而NESTED的内层回滚可被外层捕获。避免大事务:减少事务内耗时操作(如 RPC 调用),拆分为小事务。适用场景:需精细控制事务边界(如根据条件提交/回滚)。

tschen的博客 1271

Spring中进行事务管理的两种方式

1、Spring中事务管理的API PlatformTransactionManager TransactionDefinition TransactionStatus 2、编程式事务管理 3、声明式事务管理 基于Spring-AOP的方式 基于AspectJ的标签 基于注解的方式

theVicTory的博客 4122

Spring的事务管理

Spring的事务管理 事务 事务:是逻辑上一组操作, 要么全都成功, 要么全都失败. 事务特性: ACID: 原子性:事务不可分割 一致性:事务执行的前后, 数据完整性保持一致. 隔离性:一个事务执行的时候, 不应该受到其他事务的打扰 持久性:一旦结束, 数据就永久的保存到数据库. 如果不考虑隔离性: 脏读:一个事务读到另一个事务未提交数据 不可重复读:一个事务读到另一个事务已经提交数据( update) 导致一个事务多次查询结果不一致 虚读:一个事务读到另一个事务已经提交数据( ins

qq_41796988的博客 2013

Spring 事务管理

(个人学习记录)本章主要记录spring事务的两种实现方式,及编程式事务和声明式事务(xml和注解方式),在实际过程中,我们绝大多数时候都是使用的声明式事务来实现我们的事务管理。对于事务的隔离级别和传播行为我们需要重点了解。事务是一个最小的不可再分的工作单元。 一个事务对应一套完整的业务操作。事务管理是指这些操作要么全部成功执行,要么全部回滚,从而保证数据的一致性和完整性。事务是一组原子性的操作,要么全部成功提交,要么全部失败回滚。它具有 ACID 四个特性:原子性(Atomicity):事务中的操作要么全

LYH2771994122的博客 921

【Spring Framework】 Spring 事务管理

Spring 事务管理提供了一种灵活、强大的方式来管理应用程序中的事务。通过使用 Spring 事务,开发者可以轻松地实现数据的一致性和完整性。无论是编程式事务管理还是声明式事务管理,Spring 都能很好地支持各种场景的事务需求。在实际项目中,开发者应根据业务需求合理选择事务传播行为、隔离级别和事务管理器,以实现高效的事务管理。

u013675821的博客 689
上一篇: session
下一篇: 配置spring的事务管理
java_min
博客等级 码龄18年 61粉丝 161原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值