Spring中的事务

2018-09-09  本文已影响0人  我是邱邱

概念

事务是一组操作的执行单元,针对数据库操作,事务管理的是一组SQL指令,事务内的操作要不全部成功,要不全部失败。比如执行过程中,如果有一条SQL语句没有执行成功,那么这一组操作都将全部回滚

事务特性(ACID):

Atomic(原子性):要么都成功,要么都失败
Consistent(一致性):数据不应该被破坏
Isolate(隔离性):用户间操作不相混淆
Durable(持久性):永久保存

事务分类:

编程式事务

编写程序式的事务管理可以清楚的定义事务的边界,可以实现细粒度的事务控制,比如你可以通过程序代码来控制你的事务何时开始,何时结束等,与后面介绍的声明式事务管理相比,它可以实现细粒度的事务控制,例如jdbc、hibernate,但是spring中不提倡使用。

声明式事务

如果你并不需要细粒度的事务控制,你可以使用声明式事务,在Spring中,你只需要在Spring配置文件中做一些配置,即可将操作纳入到事务管理中,解除了和代码的耦合, 这是对应用代码影响最小的选择,这一点再次验证了Spring关于AOP的概念。当你不需要事务管理的时候,可以直接从Spring配置文件中移除该设置

Spring使用声明式事务,结合AOP一起使用
Spring中的事务针对方法,一般将事务用在service层

声明式事务的配置:
以下是采用JdbcTemplate方式连接的数据库的事务的配置以及数据库的连接

<context:component-scan base-package="com.qianfeng.xmltx"></context:component-scan>
        
        
     <!--  数据源对象: C3P0连接池 -->
    <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/hib1804"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
        <property name="initialPoolSize" value="3"></property>
        <property name="maxPoolSize" value="10"></property>
        <property name="maxStatements" value="100"></property>
        <property name="acquireIncrement" value="2"></property>
    </bean>
        
    <!--  JdbcTemplate工具类实例 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- spring中事务的配置 -->
    <!-- 1配置事务管理类,不同的数据库操作方法,对应的管理类不同 -->
    <bean id="txManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入连接池的对象 -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
   
   <!-- 2配置事务的增强(通知) 针对什么样的方法,采用什么样的事务处理方式
        指定事务管理类对象
    -->
   <tx:advice id="txAdvice" transaction-manager="txManage">
        <tx:attributes>
            <!-- 针对add开头的方法,事务处理时,只读属性=false、
                read-only 是否只读,如果进行增删改,必须设为false,如果是查询,设为true
                propagation 事务的传播特性
             -->
            <tx:method name="add*" read-only="false" propagation="REQUIRED"/>
            <tx:method name="delete*" read-only="false" propagation="REQUIRED"/>
            
        </tx:attributes>
   </tx:advice>
   
   <!-- 3AOP配置 -->
   <aop:config>
        <!-- 切入点 -->
        <aop:pointcut expression="execution(* com.qianfeng.xmltx.UserService.*(..))" id="pc"/>
        <!-- 针对spring中事务的配置,不需要配置切面类,spring内部根据事务操作,集成了切面类 -->
        <!-- 但是,需要告知spring,相关的方法,需要采用什么样的事务处理策略(方式) -->
        <!-- 通知 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
   
   </aop:config>
下面是采用Hibernate连接数据库的方式和Spring结合后的事务的配置:
<!-- 注解扫描  扫描指定包及其子包下的注解 -->
   <context:component-scan base-package="com.qianfeng"></context:component-scan>
  
   <!-- 数据源的配置 -->
    <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/hib1804"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
        <property name="initialPoolSize" value="5"></property>
        <property name="maxPoolSize" value="10"></property>
        <property name="maxIdleTime" value="1000"></property>
    </bean>
    
    <!-- 通过Spring创建Hibernate的SessionFactory对象 -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <!-- 将原来hibernate.cfg.xml的配置直接写入spring的配置 -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
        <!-- 配置hibernate的映射文件 -->
        <!-- <property name="mappingLocations">
            <list>
                <value>classpath:com/qianfeng/entity/User.hbm.xml</value>
                <value>classpath:com/qianfeng/entity/Person.hbm.xml</value>
                引入所有后缀是hbm.xml的映射文件
                <value>classpath:com/qianfeng/entity/*.hbm.xml</value>
            </list>
        </property> -->
        
        <!-- 扫描hibernate注解 -->
        <property name="packagesToScan" value="com.qianfeng.entity"></property>
    </bean>
   
  <!-- 1配置hibernate的事务管理类 -->
    <bean id="txManage" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <!-- 注入sessionFactory -->
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
   
    <!-- 2配置事务的特性 -->
   <tx:advice id="txAdvice" transaction-manager="txManage">
        <tx:attributes>
            <!-- 针对使用事务的add开头的方法 
            read-only 是否只读,true 是,false 可读可写
            如果有插入等操作,设为为true,运行程序会报异常-->
            <tx:method name="add*" read-only="false"/>
            
        </tx:attributes>
   </tx:advice>
   
   <!-- 3AOP配置 -->
   <aop:config>
        <!-- 切入点 -->
        <aop:pointcut expression="execution(* com.qianfeng.service.*.*(..))" id="pc"/>
   
        <!-- 通知 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
   
   </aop:config>
上一篇下一篇

猜你喜欢

热点阅读