写在前面:
接着记录自己的Spring学习之旅,若看不懂则建议先看前几篇博文,详细代码可在我的Gitee仓库ssm-learning克隆下载学习使用!
这是接着SSM之Spring中的事务控制/事务控制是啥?有什么作用?都有哪些事务控制方式的代码操作!
1.11. 3 代码操作
1.11.3.1 项目准备
- 新建项目。根据[#### 1.2.2.1 用Maven构建Spring项目]建立项目并补全所缺目录,然后建立需要的目录,结构如图
- 补全依赖。在pom文件中补全需要用的资源依赖,补全后依赖代码如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
- 新建文件。在domain目录下新建Account名类,写入以下代码:
public class Account {
private String name;
private double money;
public void setName(String name) {
this.name = name;
}
public void setMoney(double money) {
this.money = money;
}
public double getMoney() {
return money;
}
public String getName() {
return name;
}
}
- 在Dao层目录下新建AccountDao接口及其实现类,进行数据库操作!代码如下:
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void MoneyOut(String outMan, double money) {
jdbcTemplate.update("update account set money = money - ? where name = ?",money,outMan);
}
public void MoneyIn(String inMan, double money) {
jdbcTemplate.update("update account set money = money + ? where name = ?",money,inMan);
}
}
- 新建jdbc.properties文件及applicationContext文件并进行Bean注入,数据源获取,代码如下:
<bean id="accountDao" class="com.demo.dao.Impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="accountService" class="com.demo.service.Impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<context:property-placeholder location="classpath:jdbc.properties"/>
<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>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
- 新建service层类,代码如下:
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transferMoney(String outMan, String inMan, double money) {
accountDao.MoneyOut(outMan,money);
accountDao.MoneyIn(inMan,money);
}
}
- 数据库中account表数据如图
- 在controller层中编辑测试文件,模拟操作,代码如下:
public class AccountController {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService = (AccountService) applicationContext.getBean("accountService");
accountService.transferMoney("tom","jerry",500.0);
}
}
- 实现tom向Jerry借出500元操作,结果如图,成功!
1.11.3.2 xml事务配置
- 引入事务管理所用标签。将上面的复制更改一下即可,如图
- 配置平台事务管理器。代码如下:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
-配置事务通知。
<!-- 通知,事务的增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 设置事务属性信息-->
<tx:attributes>
<!-- 指定方法配置事务,可以对多个方法进行配置,其中*是通配符,可单独使用,表示所有方法-->
<tx:method name="transfer" isolation="DEFAULT" read-only="false" timeout="-1" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
- 配置事务的织入。如下:
<!-- 事务AOP的织入-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.demo.service.*.*(..))"></aop:advisor>
</aop:config>
1.11.3.3 注解事务配置
注:使用和xml配置一样的项目,将项目复制。
- 注解注入非自定义的Bean。在Service目录以及Dao层目录进行注解配置,如图
- 在Service目录下进行事务的注解配置。如图
- 删掉applicationContext文件的已用注解配置过的Bean
- 在xml中开启纾解驱动,如图
1.11.3.4 测试
1.11.3.4.1 模拟出现错误
在Service层中的实现类中写入一个错误,模拟可能会发生的错误,如图
1.11.3.4.2 数据库表配置
将数据库表数据恢复为初始状态,即
1.11.3.4.3 测试
1.11.3.4.3.1 不用事务控制
运行controller中的测试文件,查看数据库,如图。发现只有tom转出去钱了,Jerry没收到,就会造成数据丢失,出问题!
1.11.3.4.3.2 使用事务控制
运行controller中的测试文件,可发现报错了,如图
但不要慌,是意料之中的,就是要这个效果,然后看数据库变化情况,如图,没有变化,数据没有丢失,比较安全。