1、回顾事务
1.1、什么是事务?
事务在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
1.2、事务的特性【重点】
事务是恢复和并发控制的基本单位。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
2、声明式事务
声明式事务:如果你正使用一个 JEE 容器而且想让 Spring 参与到容器管理事务(Container managed transactions,CMT)的过程中,那么 Spring 应该被设置为使用 JtaTransactionManager
或由容器指定的一个子类作为事务管理器。
Spring中propagation的7种事务配置:
参考:https://blog.youkuaiyun.com/sayoko06/article/details/79164858
思考:
为什么需要配置事务?
- 如果不配置事务,可能存在数据提交不一致的情况下;
- 如果我们不在spring中去配置声明式事务,我们就需要在代码中手动配置事务!
- 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题,不容马虎!
示例:
-
导入需要依赖的jar包;
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.1</version> <scope>test</scope> </dependency> <!--连接数据库 https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.18</version> </dependency> </dependencies> <!--在build中配置resources,来防止我们资源导出失败的问题--> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
-
编写实体类;
package com.beyond.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class User { private int id; private String name; private String pwd; }
-
编写接口;
package com.beyond.mapper; import com.beyond.pojo.User; import java.util.List; public interface UserMapper { public List<User> selectUser(); //添加一个用户 public int addUser(User user); //删除一个用户 public int deleteUser(int id); }
-
导入mybatis配置和整合mybatis的文件;
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--configuration:mybatis核心配置文件--> <configuration> <!--别名--> <typeAliases> <package name="com.beyond.pojo.User"/> </typeAliases> </configuration>
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--DataSource:使用Spring的数据源替换MyBatis的配置 c3p0 dbcp druid 我们这里使用Spring提供的JDBC:org.springframework.jdbc.datasource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!--sqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--绑定MyBatis配置文件--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/beyond/mapper/UserMapper.xml"/> </bean> <!--sqlSession就是SqlSessionTemplate,SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现, 这意味着可以使用它无缝代替你代码中已经在使用的 SqlSession。 SqlSessionTemplate 是线程安全的,可以被多个 DAO 或映射器所共享使用。--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!--只能使用构造器方法注入,因为这个类它没有set方法--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> <!--配置声明式事务--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg ref="dataSource" /> </bean> <!--结合AOP实现事务的织入--> <!--配置事务通知--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!--给哪些方法配置事务--> <!--配置事务的传播特性:propagation默认REQUIRED--> <tx:attributes> <tx:method name="selectUser" read-only="true"/> <tx:method name="addUser" propagation="REQUIRED"/> <tx:method name="deleteUser" propagation="REQUIRED"/> <!--给所有的方法配置事务--> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!--配置事务切入--> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.beyond.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config> </beans>
-
编写xxxMapper.xml;
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.beyond.mapper.UserMapper"> <select id="selectUser" resultType="User"> select * from user; </select> <insert id="addUser" parameterType="User"> insert into user (id,name,pwd) values (#{id},#{name},#{pwd}); </insert> <delete id="deleteUser" parameterType="int"> deletes from user where id=#{id} </delete> </mapper>
-
编写接口的实现类;
package com.beyond.mapper; import com.beyond.pojo.User; import org.mybatis.spring.support.SqlSessionDaoSupport; import java.util.List; //方式一: public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{ public List<User> selectUser() { User user = new User(8, "小明", "uydugidio"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(8); return mapper.selectUser(); } public int addUser(User user) { return getSqlSession().getMapper(UserMapper.class).addUser(user); } public int deleteUser(int id) { return getSqlSession().getMapper(UserMapper.class).deleteUser(id); } }
-
编写spring的配置文件;
<?xml version="1.0" encoding="UTF-8"?> <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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="spring-dao.xml"/> <bean id="userMapper" class="com.beyond.mapper.UserMapperImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
-
测试。
import com.beyond.mapper.UserMapper; import com.beyond.pojo.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; public class MyTest { @Test public void test() throws Exception{ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); List<User> userList =userMapper.selectUser(); for (User user: userList) { System.out.println(user); } } }