spring之事务

it2024-12-29  9

spring之事务

事务的概念以及特点:

事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。

事务四个属性ACID

原子性(atomicity)

事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用

一致性(consistency)

一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中

隔离性(isolation)

可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏

持久性(durability)

事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

2-1 使用xml配置文件进行声明式事务的实现

2.1.1 首先创建bal表并添加数据

CREATE TABLE bal( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(20), balance INT )CHARSET = utf8; INSERT INTO bal VALUES (NULL,'刘亦菲',30000); INSERT INTO bal VALUES (NULL,'古力娜扎',100);

2.1.2 创建一个web项目或者普通项目都可以 导入需要导入的jar包

2.1.3 创建资源文件resources目录 并标记为资源目录

resources目录下创建properties目录以及spring目录

db.properties

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///chrisfeng jdbc.user=root jdbc.password=123456

aplicationContext.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--1-配置扫描包--> <context:component-scan base-package="com.zelin"/> <!--2-配置数据库属性文件--> <context:property-placeholder location="classpath:properties/db.properties"/> <!--3-配置数据源--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--4-配置事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--5-配置事务--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!--配置哪些方法执行事务--> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" read-only="false"/> <tx:method name="insert*" propagation="REQUIRED" read-only="false"/> <tx:method name="update*" propagation="REQUIRED" read-only="false"/> <tx:method name="edit*" propagation="REQUIRED" read-only="false"/> <tx:method name="delete*" propagation="REQUIRED" read-only="false"/> <tx:method name="remove*" propagation="REQUIRED" read-only="false"/> <tx:method name="trans*" propagation="REQUIRED" read-only="false"/> </tx:attributes> </tx:advice> <!--6-配置AoP--> <aop:config> <!--配置切入点--> <aop:pointcut id="pointCut" expression="execution(* com.zelin.service.impl.*ServiceImpl.*(..))"/> <!--配置切面--> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/> </aop:config> <!--7-注册JdbcTemplate模板--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> </beans>

2.1.4 src目录下创建对应的目录:pojo、service、dao、test等目录

2.1.4.1 pojo目录

Balance.java

package com.zelin.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author wf * @date 2020-10-21 16:26 */ @Data @AllArgsConstructor @NoArgsConstructor public class Balance { private int id; private String username; private double balance; }

2.1.4.2 service目录

package com.zelin.service; /** * @author wf * @date 2020-10-21 16:42 */ public interface BalanceService { void trans(int firstId, int lastId, double balance); } package com.zelin.service.impl; import com.zelin.dao.BalanceDao; import com.zelin.service.BalanceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author wf * @date 2020-10-21 16:45 */ @Service public class BalanceServiceImpl implements BalanceService { @Autowired private BalanceDao balanceDao; //1.转账操作 @Override public void trans(int firstId, int lastId, double balance) { //1.1 转出金额 balanceDao.trans(firstId,-balance); int i = 10/0; //1.2 转入金额 balanceDao.trans(lastId,balance); } }

2.1.4.3 dao目录

package com.zelin.dao; /** * @author wf * @date 2020-10-21 16:46 */ public interface BalanceDao { void trans(int id, double balance); } package com.zelin.dao.impl; import com.zelin.dao.BalanceDao; import com.zelin.pojo.Balance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; /** * @author wf * @date 2020-10-21 16:47 */ @Repository public class BalanceDaoImpl implements BalanceDao { @Autowired private JdbcTemplate jdbcTemplate; //1.执行转账操作 @Override public void trans(int id, double balance) { jdbcTemplate.update("update bal set balance = balance+? where id=?", (balance),id); } }

2.1.4.4 test目录

package com.zelin.test; import com.zelin.service.BalanceService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author wf * @date 2020-10-21 16:25 * 测试声明式事务进行转账操作 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring/applicationContext.xml") public class TestSpringTx { @Autowired private BalanceService balanceService; @Test public void test01(){ int firstId = 1; int lastId = 2; double balance = 8000; //1.转账 balanceService.trans(firstId,lastId,balance); } }

当我们在serviceImpl这个trans方法下添加一个错误:int i = 10 / 0 此时在applicationContext.xml文件中添加了事务 即使报错 也不会进行数据的修改

如果把 <tx:method name="trans" propagation=“REQUIRED” read-only=“false”/>这句话注释掉 那么转账已经转完账 但是并没有收到账 没有进行事务的回滚*

2.1.5 使用注解进行事务

2.1.5.1 可以把上面的applicationContext.xml一部分配置文件提取出来 生成新的配置文件dataSource.xml

dataSource.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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--1-配置扫描包--> <context:component-scan base-package="com.zelin"/> <!--2-配置数据库属性文件--> <context:property-placeholder location="classpath:properties/db.properties"/> <!--3-配置数据源--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--4-注册JdbcTemplate模板--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!--5-配置事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> </beans>

applicationContext2.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:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <import resource="dataSource.xml"/> <!--开启spring对事务的支持--> <tx:annotation-driven/> </beans>

2.1.5.2 test目录下进行文件的测试

package com.zelin.test; import com.zelin.service.BalanceService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author wf * @date 2020-10-21 17:44 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring/applicationContext2.xml") public class TestSpringAnno { @Autowired private BalanceService balanceService; @Test public void test01(){ int firstId = 1; int lastId = 2; double balance = 8000; //1.转账 balanceService.trans(firstId,lastId,balance); } }

2.1.5.3 service目录下的BalanceServiceImpl文件 添加一个注解@Transactional

package com.zelin.service.impl; import com.zelin.dao.BalanceDao; import com.zelin.service.BalanceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * @author wf * @date 2020-10-21 16:45 */ @Service @Transactional public class BalanceServiceImpl implements BalanceService { @Autowired private BalanceDao balanceDao; //1.转账操作 @Override public void trans(int firstId, int lastId, double balance) { //1.1 转出金额 balanceDao.trans(firstId,-balance); //int i = 10/0; //1.2 转入金额 balanceDao.trans(lastId,balance); } }

可以得出同样的效果 即配置了事务 如果出错就可以进行的回滚rollback操作

最新回复(0)