声明式事务
1.事务的特定
- 把一组业务当成一个业务来做,要么都成功,要么都失败
- 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不容马虎
- 确保完整性和一致性
事务的ACID原则
- 原子性
- 一致性
- 隔离性
- 持久性
一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理
spring中的事务管理
- 声明式事务:AOP,横切进去的,不需要改变程序(推荐使用)
-
编程式事务:需要在代码中,进行事务的管理
使用事务
在我们原有的项目中的Spring主配置applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataresource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataresource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="userserviceimpl" class="com.cbbpp.mapper.UserMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataresource" />
</bean>
<!--结合AOP实现事务的织入-->
<!--配置事务的类-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给那些方法配置事务-->
<!--配置事务的传播特性propagation-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete"/>
<tx:method name="update"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务的切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.cbbpp.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
特别是要注意,在使用AOP时候,我们测试启动类代码中.getBean()中的类型为接口而不是实现类,如下:
import com.cbbpp.mapper.UserMapper;
import com.cbbpp.mapper.UserMapperImpl;
import com.cbbpp.pojo.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userserviceimpl = context.getBean("userserviceimpl", UserMapper.class);
List<User> users = userserviceimpl.selectUser();
for (User user : users) {
System.out.println(user);
}
}
}
而不是下面这种,不然会报Proxy错
UserMapperImpl userserviceimpl = context.getBean("userserviceimpl", UserMapperImpl.class);
思考:
- 如果不配置事务,可能存在数据提交不一致的情况
- 如果我们不在Spring中去配置声明式事务,我们就需要手动去在代码中配置事务
- 事务在项目开发中十分重要,涉及到数据库的一致性和完整性问题,不容马虎