1 > POM文件需要的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring_dome</artifactId>
<groupId>com.parent</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring_transcation</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
</dependencies>
</project>
2 > 编写需要用到的类
2.1 Dao层接口及其实现类
2.1.1 > AccountDao 接口
package com.tran.dao;
import com.tran.domain.Account;
import java.util.List;
public interface AccountDao {
List<Account> findAllAccount();
Integer saveAccount(Account account);
Integer updateAccount(Account account);
Integer updateAccountToAccount(Account source , Account target,Float transferMoney);
}
2.1.2 > AccountDaoImpl 接口实现类,此实现类只负责逻辑代码的实现,事物控制由spring实现
package com.tran.dao.impl;
import com.tran.dao.AccountDao;
import com.tran.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import java.util.List;
public class AccountDaoImpl implements AccountDao {
private DriverManagerDataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DriverManagerDataSource dataSource) {
this.dataSource = dataSource;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public List<Account> findAllAccount() {
return jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
}
@Override
public Integer saveAccount(Account account) {
return null;
}
@Override
public Integer updateAccount(Account account) {
StringBuilder sb = new StringBuilder("update account set ");
if (account == null || account.getId() == null) {
System.out.println("Id is null ~");
throw new RuntimeException("Execute Fail ~~ : by ID Field is null ~~");
} else {
if (account.getName() == null) {
System.out.println("Name is null ~");
if (account.getMoney() != null) {
System.out.println("Money is : " + account.getMoney());
sb.append("money = " + account.getMoney() + " ");
} else {
System.out.println("Money is null ~");
throw new RuntimeException("Need's Values is null ~ \ncannot update ~ \nBy id is : " + account.getId());
}
} else {
System.out.println("Name is : " + account.getName());
sb.append("name = '" + account.getName() + "' ");
if (account.getMoney() != null) {
System.out.println("Money is : " + account.getMoney());
sb.append(", money = " + account.getMoney() + " ");
} else {
System.out.println("Money is null ~");
}
}
sb.append("where id = " + account.getId());
String sql_update = sb.toString();
System.out.println("SQL is : " + sql_update);
int i = 0;
i = jdbcTemplate.update(sql_update);
return i;
}
}
@Override
public Integer updateAccountToAccount(Account source, Account target, Float transferMoney) {
Integer update_line = 0;
String sql_findById = "select * from account where id = ?";
Account account_source = jdbcTemplate.queryForObject(sql_findById, new BeanPropertyRowMapper<Account>(Account.class), source.getId());
Account account_target = jdbcTemplate.queryForObject(sql_findById, new BeanPropertyRowMapper<Account>(Account.class), target.getId());
if (account_source != null && account_target != null) {
if (transferMoney > 0.0f) {
if (account_source.getMoney() > transferMoney) {
System.out.println(account_source.getName() + " --> " +
account_target.getName() + " : Money( "+ transferMoney +" )");
account_source.setMoney(account_source.getMoney() - transferMoney);
account_target.setMoney(account_target.getMoney() + transferMoney);
update_line += this.updateAccount(account_source);
update_line += this.updateAccount(account_target);
} else {
throw new RuntimeException("余额不足!! 请重新输入!!");
}
} else {
throw new RuntimeException("您输入的金额为负数!! 请重新输入!!");
}
} else {
throw new RuntimeException("获取到的值是空的!! 请检查您输入的账户是否存在 !!");
}
System.out.println("Update line is : " + update_line);
if (update_line == 2) {
System.out.println("Update success !!!");
} else {
System.out.println("Update fail !!");
throw new RuntimeException();
}
return update_line;
}
}
2.2 Service 层接口及其实现类
2.2.1 AccountService 接口
package com.tran.service;
import com.tran.domain.Account;
import java.util.List;
public interface AccountService {
List<Account> findAllAccount();
Integer transferAccount(Account source,Account target,Float money);
}
2.2.2 AccountServiceImpl 实现类
package com.tran.service.impl;
import com.tran.dao.AccountDao;
import com.tran.domain.Account;
import com.tran.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public List<Account> findAllAccount() {
return accountDao.findAllAccount();
}
@Override
public Integer transferAccount(Account source, Account target, Float money) {
return accountDao.updateAccountToAccount(source,target,money);
}
}
3 > bean.xml (springIOC容器配置,配置需要加载进IOC容器的类)
同时配置需要加载的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"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 设置DataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://159.75.19.211:3306/dome02"/>
<property name="username" value="root"/>
<property name="password" value="111222333"/>
</bean>
<!-- JdbcTemplate设置数据源 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<!-- 设置Dao层 -->
<bean id="accountDao" class="com.tran.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!-- 配置Service层 -->
<bean id="accountService" class="com.tran.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!-- 生成事务管理器 -->
<bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 这快需要池,就很好理解了,事务肯定要对某一个或者多个链接产生一个约束,因此需要一个被管理的链接池 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 设置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManger">
<tx:attributes>
<!--
isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。
-->
<!-- find*表示AccountDaoimpl下的所有方法 -->
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="update*" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- 配置Aop切面 -->
<aop:config>
<!-- 配置切入点 切入点为AccountDaoImpl中的一个方法 -->
<aop:pointcut id="pointcut01" expression="execution(* com.tran.dao.impl.AccountDaoImpl.*(..))"/>
<!-- 配置事务管理通知,txAdvice表示事务通知,与上面设置的事物通知相对应 -->
<aop:advisor pointcut-ref="pointcut01" advice-ref="txAdvice"/>
</aop:config>
</beans>
4 > 编写测试类
4.1 > Test 测试类(背景换成小姐姐,心情都变得愉悦了)
4.2 > Account表
4.2 > 测试账户1- 转给-账户2 100(无异常发生,模拟正常情况)
4.3 > 测试账户1- 转给-账户2 100(异常发生,模拟发生错误情况,此时需要回滚)
aaa转账给bbb ,100由于发生未知错误,发生回滚,账户内数额不变
|