手動實現IOC與事務控制基於JDBC
sql
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`name` varchar(50) NOT NULL COMMENT ' 姓名',
`cardNo` varchar(50) NOT NULL COMMENT '卡號',
`money` int(11) NOT NULL COMMENT '金額'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of account
-- ----------------------------
INSERT INTO `account` VALUES ('張三', '123456', '10000');
INSERT INTO `account` VALUES ('李四', '456789', '10000');
新建項目
pom.xml
<?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>stage01-spring</artifactId>
<groupId>com.liu</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-classroom</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.71</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>9099</port>
<path>/</path>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
</project>
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="false">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Servlet
package com.liu.spring.servlet;
import com.alibaba.fastjson.JSON;
import com.liu.spring.factory.BeanFactory;
import com.liu.spring.result.Result;
import com.liu.spring.service.TransferService;
import com.liu.spring.service.impl.TransferServcieImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
/**
* @Description
* @ClassName TransferServlet
* @Author 劉楠
* @date 2020.06.24
*/
@WebServlet(name = "transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
/**
* http mine,json類型
*/
public static final String MIME_TYPE_JSON = "application/json";
/**
* http mine,json類型指定utf-8編碼
*/
public final static String MIME_TYPE_JSON_UTF8 = MIME_TYPE_JSON + ";charset=UTF-8";
//1.實例化TransferService
private TransferService transferService = new TransferServcieImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//設置請求的字體編碼
req.setCharacterEncoding("UTF-8");
String fromCardNo=req.getParameter("fromCardNo");
String toCardNo=req.getParameter("toCardNo");
String moneyValue = req.getParameter("money");
Integer money = Integer.valueOf(moneyValue);
//默認就是200
Result result = new Result();
try {
transferService.transfer(fromCardNo, toCardNo,money);
} catch (Exception e) {
e.printStackTrace();
result.setResult(Result.ResultEnum.SERVER_ERROR);
}
//設置響應字符編碼
resp.setContentType(MIME_TYPE_JSON_UTF8);
resp.getWriter().println(JSON.toJSON(result));
}
}
##### Result
```java
/**
* @Description
* @ClassName Result
* @Author 劉楠
* @date 2020.06.24
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = -645547982453859521L;
private Integer status;
private String message;
private T data;
public Result() {
this(ResultEnum.SUCCESS);
}
public Result(ResultEnum result) {
setResult(result.getStatus(), result.getMessage());
}
public void setResult(ResultEnum result) {
status = result.getStatus();
message = result.getMessage();
}
public void setResult(int status, String message) {
this.status = status;
this.message = message;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return new StringJoiner(", ", Result.class.getSimpleName() + "[", "]")
.add("status=" + status)
.add("message='" + message + "'")
.add("data=" + data)
.toString();
}
public enum ResultEnum {
SUCCESS(200),
PARAM_ERROR(400),
NO_AUTH(401),
FORBIDDEN(403),
SERVER_ERROR(500),
FAILED(-1);
private int status;
private final static String[] initMsgs = { "執行成功","提交的數據錯誤","身份驗證失敗","無權限訪問","執行錯誤","執行失敗" };
private ResultEnum(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
/**
* 返回結果描述.
*
* @return 結果描述String
*/
public String getMessage() {
switch (status) {
case 200:
return initMsgs[0];
case 400:
return initMsgs[1];
case 401:
return initMsgs[2];
case 403:
return initMsgs[3];
case 500:
return initMsgs[4];
case -1:
return initMsgs[5];
default:
break;
}
return null;
}
}
}
service
public interface TransferService {
boolean transfer(String fromAccount, String toAccount, Integer money) throws SQLException, Exception;
}
service 實體類
package com.liu.spring.service.impl;
import com.liu.spring.dao.AccountDao;
import com.liu.spring.dao.impl.AccountDaoImpl;
import com.liu.spring.entity.Account;
import com.liu.spring.factory.BeanFactory;
import com.liu.spring.service.TransferService;
import com.liu.spring.transaction.TransactionManager;
import com.liu.spring.util.ConnectionUtils;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @Description
* @ClassName TransferServcieImpl
* @Author 劉楠
* @date 2020.06.23
*/
public class TransferServcieImpl implements TransferService {
private AccountDao accountDao = new AccountDaoImpl();
@Override
public boolean transfer(String fromAccount, String toAccount, Integer money) throws Exception {
System.out.println("=====開始轉賬==== ");
Account fAccount = accountDao.queryByCardNo(fromAccount);
Account tAccount = accountDao.queryByCardNo(toAccount);
fAccount.setMoney(fAccount.getMoney()-money);
tAccount.setMoney(tAccount.getMoney()+money);
accountDao.updateAccountByCardno(fAccount);
//int i=1/0; 異常用於測試 事務
accountDao.updateAccountByCardno(tAccount);
return true;
}
}
dao
public interface AccountDao {
/**
* 根據卡號查詢
* @param cardNo
* @return
*/
Account queryByCardNo(String cardNo) throws SQLException;
int updateAccountByCardno(Account fAccount) throws SQLException;
}
dao實現類
package com.liu.spring.dao.impl;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.liu.spring.dao.AccountDao;
import com.liu.spring.entity.Account;
import com.liu.spring.util.ConnectionUtils;
import com.liu.spring.util.DruidUtils;
import javax.swing.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Description
* @ClassName AccountDaoImpl
* @Author 劉楠
* @date 2020.06.23
*/
public class AccountDaoImpl implements AccountDao {
@Override
public Account queryByCardNo(String cardNo) throws SQLException {
//從連接池獲取連接
Connection connection = DruidUtils.getInstance().getConnection();
System.out.println("queryByCardNo connection "+connection.toString());
String sql = "select name ,cardNo ,money from account where cardNo=?";
//預編譯SQL
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//填充參數
preparedStatement.setString(1, cardNo);
//執行查詢
ResultSet resultSet = preparedStatement.executeQuery();
Account account = null;
while (resultSet.next()) {
account = new Account();
account.setMoney(resultSet.getInt("money"));
account.setCardNo(resultSet.getString("cardNo"));
account.setName(resultSet.getString("name"));
}
preparedStatement.close();
connection.close();
return account;
}
@Override
public int updateAccountByCardno(Account fAccount) throws SQLException {
Connection connection = DruidUtils.getInstance().getConnection();
System.out.println("updateAccountByCardno connection "+connection.toString());
String sql = "update account set money =? where cardNo=? ";
//預編譯SQL
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//設置參數
preparedStatement.setInt(1, fAccount.getMoney());
preparedStatement.setString(2, fAccount.getCardNo());
//執行更新
int update = preparedStatement.executeUpdate();
preparedStatement.close();
connection.close();
return update;
}
}
實體類
public class Account implements Serializable {
private static final long serialVersionUID = -6836411742270629093L;
/**
* 帳戶名稱
*/
private String name;
/**
* 卡號
*/
private String cardNo;
/**
* 金額,餘額
*/
private Integer money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
}
工具類
DruidUtils
public class DruidUtils {
private DruidUtils(){
}
private static DruidDataSource druidDataSource = new DruidDataSource();
static {
druidDataSource.setUrl("jdbc:mysql://127.0.0.1/bank?characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false");
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setPassword("root");
}
public static DruidDataSource getInstance(){
return druidDataSource;
}
public static void main(String[] args) throws SQLException {
System.out.println(DruidUtils.getInstance().getConnection().toString());
}
}
使用tomcat7插件啓動
測試 postman
正常執行沒有問題
數據庫也正常,
打開異常代碼-重啓項目
再次發送同樣的請求
看數據庫
第一個記錄扣了錢,但第二記錄並沒有增加,錢不見了,因爲沒有事務控制
現在的問題
- Servlet中使用了new 關鍵字創建Service–代碼耦合
- Service中也使用的new 創建dao—代碼耦合
- 沒有事務事務
一共2個大問題
代碼代碼耦合
* 使用工廠來創建對象,不使用new
沒有事務
- 在servcie中的select,update方法每次都會創建一個新的連接,這樣不是一個Connection,
- 同時每次執行完都把連接關閉了,再次又要重新獲取新連接 肯定不是一個事務的見下方代碼
* 事務控制JDBC默認是在dao層Connection對象的,控制在Service層中,解決就是把事務控制放在Service中
解決第一個問題-代碼耦合
使用工廠來解決
使用配置文件的方式來聲明bean
beans.xml
<beans>
<!--id標識 class 類的全限定類名-->
<bean id="transferService" class="com.liu.spring.service.impl.TransferServcieImpl">
<property name="AccountDao" ref="accountDao"/>
</bean>
<bean id="accountDao" class="com.liu.spring.dao.impl.AccountDaoImpl">
</bean>
</beans>
只是名稱和spring一樣,沒有任何關係
1.創建工廠來解析XML,
2.把對象實例保存
3. 提供接口獲取對象
package com.liu.spring.factory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Description 使用反射創建對象
* @ClassName BeanFactory
* @Author 劉楠
* @date 2020.06.24
*/
public class BeanFactory {
/**
* 1.解析xml,將bean保存
* 2.提供獲取對象的接口
*/
/**
* 保存對象
*/
private static Map<String, Object> beansMap = new ConcurrentHashMap<>();
private static String beansXml="beans.xml";
static {
//解析xml 保存在map中
//1.加載xml
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream(beansXml);
try {
Document document = new SAXReader().read(in);
//獲取根據節點
Element rootElement = document.getRootElement();
//獲取所有bean的標籤
List<Element> beanList = rootElement.selectNodes("//bean");
for (Element element : beanList) {
/**
* 獲取每個元素的id、class屬性
*/
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");
/**
* 通過反射創建對象
*/
Class<?> cla = Class.forName(clazz);
//實例化之後的對象
Object instance = cla.newInstance();
/**
* 放入map中
*/
beansMap.put(id, instance);
}
//實例化後,維護對象的依賴關係
List<Element> propertyList = rootElement.selectNodes("//property");
//解析property獲取父元素
for (Element element : propertyList) {
String name = element.attributeValue("name");
String ref = element.attributeValue("ref");
//找到當前需要被處理依賴關係的Bean
Element parent = element.getParent();
//調用父元素的反射功能
String parantId = parent.attributeValue("id");
Object parantObject = beansMap.get(parantId);
Method[] methods = parantObject.getClass().getMethods();
for (Method method : methods) {
String methodName = method.getName();
//這個方法是要要賦值的方法
if(methodName.equalsIgnoreCase("set"+name)){
method.invoke(parantObject, beansMap.get(ref));
}
}
//重新放入容器
beansMap.put(parantId, parantObject);
}
} catch (DocumentException | ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 根據id獲取對象
* @param id
* @return
*/
public static Object getBean(String id){
Object o = beansMap.get(id);
return o;
}
}
修改servlet 與service
TransferServlet
@WebServlet(name = "transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
/**
* http mine,json類型
*/
public static final String MIME_TYPE_JSON = "application/json";
/**
* http mine,json類型指定utf-8編碼
*/
public final static String MIME_TYPE_JSON_UTF8 = MIME_TYPE_JSON + ";charset=UTF-8";
//1.實例化TransferService
// private TransferService transferService = new TransferServcieImpl();
private TransferService transferService =(TransferService) BeanFactory.getBean("transferService");
...
}
service
public class TransferServcieImpl implements TransferService {
// private AccountDao accountDao = new AccountDaoImpl();
private AccountDao accountDao ;
/**
* 提供get,set方法
* @return
*/
public AccountDao getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
啓動並把異常代碼註釋
執行成功,但打開異常代碼後,還是不行的,因爲沒有事務控制在Service中
解決第二個大問題
- 在servcie中的select,update方法每次都會創建一個新的連接,這樣不是一個Connection,
- 同時每次執行完都把連接關閉了,再次又要重新獲取新連接
- 事務控制JDBC默認是在dao層Connection對象的,控制在Service層中,解決就是把事務控制放在Service中
####### 1.每次都創建新連接
一個請求到Server後就一個線程在處理,可不可把當前線程與Connection綁定在一起這樣就解決了呢?
新建ConnectionUtils工具類來實現
/**
* @Description
* @ClassName ConnectionUtils
* @Author 劉楠
* @date 2020.06.24
*/
public class ConnectionUtils {
/**
* 單例
*/
private ConnectionUtils(){
}
private static ConnectionUtils connectionUtils = new ConnectionUtils();
/**
* 使用ThreadLocal與Connection綁定
*/
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
public static ConnectionUtils getInstance(){
return connectionUtils;
}
public Connection getCurrentConnection() throws SQLException {
//先直接從當前線程取
Connection connection =threadLocal.get();
//判斷是否爲空
if(connection==null){
//空就從工具類中創建一個連接Connection
connection = DruidUtils.getInstance().getConnection();
//Connection與當前線程綁定
threadLocal.set(connection);
}
//返回連接
return connection;
}
}
- Connection每次使用完都關閉了?我們不關閉就好了嗎
改造Dao層
public class AccountDaoImpl implements AccountDao {
@Override
public Account queryByCardNo(String cardNo) throws SQLException {
//從連接池獲取連接
// Connection connection = DruidUtils.getInstance().getConnection();
/**
* 獲取當前線程的Connection
*/
Connection connection = ConnectionUtils.getInstance().getCurrentConnection();
System.out.println("queryByCardNo connection " + connection.toString());
String sql = "select name ,cardNo ,money from account where cardNo=?";
//預編譯SQL
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//填充參數
preparedStatement.setString(1, cardNo);
//執行查詢
ResultSet resultSet = preparedStatement.executeQuery();
Account account = null;
while (resultSet.next()) {
account = new Account();
account.setMoney(resultSet.getInt("money"));
account.setCardNo(resultSet.getString("cardNo"));
account.setName(resultSet.getString("name"));
}
preparedStatement.close();
//關閉後就不是當前線程了
// connection.close();
return account;
}
@Override
public int updateAccountByCardno(Account fAccount) throws SQLException {
// Connection connection = DruidUtils.getInstance().getConnection();
/**
* 獲取當前線程的Connection
*/
Connection connection = ConnectionUtils.getInstance().getCurrentConnection();
System.out.println("updateAccountByCardno connection " + connection.toString());
String sql = "update account set money =? where cardNo=? ";
//預編譯SQL
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//設置參數
preparedStatement.setInt(1, fAccount.getMoney());
preparedStatement.setString(2, fAccount.getCardNo());
//執行更新
int update = preparedStatement.executeUpdate();
preparedStatement.close();
//關閉後就不是當前線程了
// connection.close();
return update;
}
}
測試下Connection是不是同一個
發一個請求
改造Servcie層-使用手動事務-異常未開啓
package com.liu.spring.service.impl;
import com.liu.spring.dao.AccountDao;
import com.liu.spring.dao.impl.AccountDaoImpl;
import com.liu.spring.entity.Account;
import com.liu.spring.factory.BeanFactory;
import com.liu.spring.service.TransferService;
import com.liu.spring.transaction.TransactionManager;
import com.liu.spring.util.ConnectionUtils;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @Description
* @ClassName TransferServcieImpl
* @Author 劉楠
* @date 2020.06.23
*/
public class TransferServcieImpl implements TransferService {
// private AccountDao accountDao = new AccountDaoImpl();
private AccountDao accountDao ;
@Override
public boolean transfer(String fromAccount, String toAccount, Integer money) throws Exception {
System.out.println("=====開始轉賬==== ");
try {
/**
* 開啓事務關閉事務的自動提交
*/
ConnectionUtils.getInstance().getCurrentConnection().setAutoCommit(false);
Account fAccount = accountDao.queryByCardNo(fromAccount);
Account tAccount = accountDao.queryByCardNo(toAccount);
fAccount.setMoney(fAccount.getMoney()-money);
tAccount.setMoney(tAccount.getMoney()+money);
accountDao.updateAccountByCardno(fAccount);
//int i=1/0;
accountDao.updateAccountByCardno(tAccount);
/**
* 正常執行完成 提交事務
*/
ConnectionUtils.getInstance().getCurrentConnection().commit();
}catch (Exception e){
e.printStackTrace();
/**
* 有異常回滾事務
*/
ConnectionUtils.getInstance().getCurrentConnection().rollback();
//拋出異常 便於上層 捕獲
throw new RuntimeException(e);
}
return true;
}
/**
* 提供get,set方法
* @return
*/
public AccountDao getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
測試下
打開異常代碼
測試
重點看數據庫
並沒有出現最開始的現象
優化,將事務的開啓,提交,回滾提取到一個公共類中
package com.liu.spring.transaction;
import com.liu.spring.util.ConnectionUtils;
import java.sql.SQLException;
/**
* @Description 負責手動事務的開啓,提交 ,回滾
* @ClassName TransactionManager 事務管理器
* @Author 劉楠
* @date 2020.06.24
*/
public class TransactionManager {
private static TransactionManager INSTANCE = new TransactionManager();
private TransactionManager(){
}
public static TransactionManager getInstance(){
return INSTANCE;
}
/**
* 開啓事務
*/
public void beginTransaction() throws SQLException {
ConnectionUtils.getInstance().getCurrentConnection().setAutoCommit(false);
}
/**
* 提交事務
*/
public void commitTransaction() throws SQLException {
ConnectionUtils.getInstance().getCurrentConnection().commit();
}
/**
* 回滾事務
*/
public void rollbackTransaction() throws SQLException {
ConnectionUtils.getInstance().getCurrentConnection().rollback();
}
}
改造Service
package com.liu.spring.service.impl;
import com.liu.spring.dao.AccountDao;
import com.liu.spring.dao.impl.AccountDaoImpl;
import com.liu.spring.entity.Account;
import com.liu.spring.factory.BeanFactory;
import com.liu.spring.service.TransferService;
import com.liu.spring.transaction.TransactionManager;
import com.liu.spring.util.ConnectionUtils;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @Description
* @ClassName TransferServcieImpl
* @Author 劉楠
* @date 2020.06.23
*/
public class TransferServcieImpl implements TransferService {
// private AccountDao accountDao = new AccountDaoImpl();
private AccountDao accountDao ;
@Override
public boolean transfer(String fromAccount, String toAccount, Integer money) throws Exception {
System.out.println("=====開始轉賬==== ");
try {
/**
* 開啓事務關閉事務的自動提交
*/
// ConnectionUtils.getInstance().getCurrentConnection().setAutoCommit(false);
//使用事務管理器-開啓使用
TransactionManager.getInstance().beginTransaction();
Account fAccount = accountDao.queryByCardNo(fromAccount);
Account tAccount = accountDao.queryByCardNo(toAccount);
fAccount.setMoney(fAccount.getMoney()-money);
tAccount.setMoney(tAccount.getMoney()+money);
accountDao.updateAccountByCardno(fAccount);
int i=1/0;
accountDao.updateAccountByCardno(tAccount);
/**
* 正常執行完成 提交事務
*/
// ConnectionUtils.getInstance().getCurrentConnection().commit();
//使用事務管理器-提交事務
TransactionManager.getInstance().commitTransaction();
}catch (Exception e){
e.printStackTrace();
/**
* 有異常回滾事務
*/
// ConnectionUtils.getInstance().getCurrentConnection().rollback();
//使用事務管理器回滾事務
TransactionManager.getInstance().rollbackTransaction();
//拋出異常 便於上層 捕獲
throw new RuntimeException(e);
}
return true;
}
/**
* 提供get,set方法
* @return
*/
public AccountDao getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
再次測試異常情況
並沒有改變,
測試下正常情況
註釋異常代碼
提交成功
這樣事務就改選到Service中了,改造完成
代碼:https://gitee.com/null_631_9084/myhomework/tree/master/stage01-spring/spring-classroom
還存在一些問題,後期優化
每個方法方法都有一大段try-catch代碼不太友好