概念
事务是一组操作的执行单元,针对数据库操作,事务管理的是一组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>
网友评论