###需求:有以下三張表
1.書名錶spring
CREATE TABLE `t_book` ( `book_id` int(4) NOT NULL AUTO_INCREMENT, `book_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `book_price` decimal(4,2) DEFAULT NULL, PRIMARY KEY (`book_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1003 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
2.庫存表sql
CREATE TABLE `t_stock` ( `stock_id` int(4) NOT NULL AUTO_INCREMENT, `stock_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `stock_num` int(4) DEFAULT NULL, PRIMARY KEY (`stock_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1002 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.用戶餘額表app
CREATE TABLE `t_user` ( `user_id` int(4) NOT NULL AUTO_INCREMENT, `user_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `balance` decimal(6,2) DEFAULT NULL, PRIMARY KEY (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1002 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
業務需求:
1.先從書名錶中獲取該書的價格
2.買一本書,即更新庫存表該書的數量
3.更新用戶餘額表的餘額
###接口層設計ide
public interface BookShopDao { //根據書號獲取書的價格 public double getBookPriceByBookId(int bookId); //更新書的庫存,減一 public void updateBookStock(int bookId); //更新用戶帳戶餘額 public void updateUserBalance(int userId,double price); }
###接口實現層設計測試
package com.test.spring.tx; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository("bookShopDao") public class BookShopDaoImpl implements BookShopDao { @Autowired private JdbcTemplate jdbcTemplate; /** * 獲取書的價格 */ @Override public double getBookPriceByBookId(int bookId) { String sql = "SELECT tb.book_price FROM t_book tb WHERE tb.book_id=?"; return jdbcTemplate.queryForObject(sql, Double.class,bookId); } /** * 更新庫存 */ @Override public void updateBookStock(int bookId) { //檢查庫存是否足夠,若不夠,則拋出異常 String sqlCheck = "SELECT ts.stock_num FROM t_stock ts WHERE ts.stock_id=?"; int stockNum = jdbcTemplate.queryForObject(sqlCheck, Integer.class,bookId); if (stockNum <= 0) { throw new BookStockException("庫存不足"); } String sql = "UPDATE t_stock SET stock_num=stock_num-1 WHERE stock_id = ?"; jdbcTemplate.update(sql, bookId); } /** * 更新帳戶餘額 */ @Override public void updateUserBalance(int userId, double price) { //驗證餘額是否足夠,若不夠,則拋出異常 String sql2 ="SELECT tu.balance FROM t_user tu WHERE tu.user_id= ?"; double balance = jdbcTemplate.queryForObject(sql2, Double.class,userId); if (balance < price) { throw new UserBalanceException("餘額不足"); } String sql = "UPDATE t_user SET balance=balance-? WHERE user_id= ?"; jdbcTemplate.update(sql, price, userId); } }
###測試代碼spa
package com.test.spring.tx; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.transaction.annotation.Transactional; public class TestTx { private ApplicationContext ctx; private BookShopDao bookShopDao; private BookShopService bookShopService; { ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); bookShopDao = ctx.getBean(BookShopDao.class); bookShopService = ctx.getBean(BookShopService.class); } /** * 獲取書的單價 */ @Test public void testgetBookPrice() { System.out.println(bookShopDao.getBookPriceByBookId(1000)); } /** * 更新書的庫存 */ @Test public void testUpdateBookStock(){ bookShopDao.updateBookStock(1001); } /** * 更新用戶金額 */ @Test public void testUpdateUserBalance(){ bookShopDao.updateUserBalance(1000, 20); } }
###庫存不足異常類設計
package com.test.spring.tx; @SuppressWarnings("serial") 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 } }
###用戶餘額不足異常類code
package com.test.spring.tx; @SuppressWarnings("serial") public class UserBalanceException extends RuntimeException{ public UserBalanceException() { super(); // TODO Auto-generated constructor stub } public UserBalanceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); // TODO Auto-generated constructor stub } public UserBalanceException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public UserBalanceException(String message) { super(message); // TODO Auto-generated constructor stub } public UserBalanceException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } }
###xml文件配置component
<context:component-scan base-package="com.test.spring.tx"></context:component-scan> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置數據源 --> <bean id="dataSources" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSources"></property> </bean>