Spring 為什麼要用到事務的準備?
阿新 • • 發佈:2018-12-25
事務就是一個整個的過程,過程只有兩個結果,成功和失敗!
為什麼用到事務呢?
以下是例項
需求:這個模擬一個書店的銷售過程,當客戶買走書以後,書的庫存減少,而且客戶的賬戶餘額會減少
書的編號 名稱 價格
書的編號 庫存
使用者名稱 賬戶餘額
總共涉及七個類,一個xml檔案
首先是一個介面類
package cn.com.day04; public interface BookShopDao { //根據書號獲取書的單價 public int findBookPriceByIsbn(String isbn); //更新書的庫存,使得書號對應的庫存-1 public void updateBookStock(String isbn); //更新使用者的賬戶餘額,使得username的balance-price public void updateUserAccount(String username,int price); }
實現類
package cn.com.day04; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class BookShopDaoImpl implements BookShopDao { @Autowired private JdbcTemplate jdbcTemplate = new JdbcTemplate(); // 根據貨號查詢價格 public int findBookPriceByIsbn(String isbn) { String sql = "select price from bookinfo where isbn=?"; int price = jdbcTemplate.queryForObject(sql, Integer.class, isbn); return price; } // 根據貨號更新庫存 public void updateBookStock(String isbn) { // 資料庫沒有約束,如果庫存不足的話就需要手動的新增約束 String sql0 = "select stock from bookstock where isbn=?"; int stock = jdbcTemplate.queryForObject(sql0, Integer.class, isbn); if (stock == 0) { throw new BookStockException("庫存不足...."); } String sql = "update bookstock set stock=stock-1 where isbn=? "; jdbcTemplate.update(sql, isbn); } // 根據使用者名稱和價格更新使用者賬戶餘額 public void updateUserAccount(String username, int price) { // 資料庫沒有約束,如果庫存不足的話就需要手動的新增約束 String sql0 = "select count from usercount where username=?"; int count = jdbcTemplate.queryForObject(sql0, Integer.class, username); if (count < price) { throw new BookCountException("餘額不足...."); } String sql1 = "update usercount set count=count-? where username=? "; jdbcTemplate.update(sql1, price, username); } }
手動定義異常1
package cn.com.day04; public class BookCountException extends RuntimeException { public BookCountException() { super(); // TODO Auto-generated constructor stub } public BookCountException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); // TODO Auto-generated constructor stub } public BookCountException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public BookCountException(String message) { super(message); // TODO Auto-generated constructor stub } public BookCountException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } }
手動定義異常2
package cn.com.day04;
public class BookStockException extends RuntimeException{
public BookStockException() {
super();
// TODO Auto-generated constructor stub
}
public BookStockException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public BookStockException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public BookStockException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public BookStockException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
測試類
package cn.com.day04;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestFact {
private static ApplicationContext ioc = null;
private static BookShopDaoImpl bookShopDaoImpl = null;
static {
ioc = new ClassPathXmlApplicationContext("bean-jdbc.xml");
bookShopDaoImpl = ioc.getBean(BookShopDaoImpl.class);
}
public void test1() {
System.out.println(bookShopDaoImpl.findBookPriceByIsbn("1002"));
}
public void test2() {
bookShopDaoImpl.updateBookStock("1001");
}
@Test
public void test3() {
bookShopDaoImpl.updateUserAccount("楊楓述", 28);
}
}
到這裡都是測試沒有問題的!
但是買書,書的庫存減少,賬戶餘額減少,是一個整個過程,
於是乎
整合了一下程式碼
介面類
package cn.com.day04;
public interface BookShopService {
public void purchase(String username,String isbn);
}
實現類
package cn.com.day04;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("bookShopService")
public class BookShopServiceImpl implements BookShopService{
@Autowired
private BookShopDaoImpl bookShopDaoImpl;
@Override
public void purchase(String username, String isbn) {
//1.根據書的編號來查詢價格
int price=bookShopDaoImpl.findBookPriceByIsbn(isbn);
//2.更新書的庫存
bookShopDaoImpl.updateBookStock(isbn);
//2.根據使用者名稱查詢餘額,扣除書的價格
bookShopDaoImpl.updateUserAccount(username, price);
}
}
在測試的時候,就發現一個問題,如果一個人的餘額不夠付這個書的價格的話,整個過程雖然會丟擲我們剛才手動定義的異常
提示餘額不足,但是書的庫存還是減少了;
這個過程最後的結果明明沒有交易成功,但是庫存還是減少了!
這個就是我們需要用到事務的原因了