Spring通過事務實現模擬銀行轉賬案例
阿新 • • 發佈:2019-01-31
1. 案例結構
2. 所用資料庫表
3. jdbc.properties配置檔案
driver=com.mysql.jdbc.Driver
url=jdbc\:mysql\://localhost\:3306/test?characterEncoding\=utf-8
username=root
password=root
initialSize=5
maxActive=50
maxIdle=10
minIdle=5
4. 1 applicationContext.xml 註解方式4.2 applicationContext.xml XML方式<?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:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd "> <!-- 啟用註解 --> <context:annotation-config/> <!--掃描生成單例實體物件 --> <context:component-scan base-package="com.zhq.*"/> <!-- 用於載入連線資料庫的屬性檔案 --> <bean id="preferencesPlaceholderConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="location" value="classpath:config/jdbc.properties"/> </bean> <!--配置資料來源,建立與資料庫的連線池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${driver}"></property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> <!--連線池配置 --> <property name="initialSize" value="${initialSize}"></property> <property name="maxActive" value="${maxActive}"></property> <property name="maxIdle" value="${maxIdle}"></property> <property name="minIdle" value="${minIdle}"></property> </bean> <!--採用Spring提供的Jdbc物件,可以操作資料 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!--配置資料來源物件 --> <constructor-arg ref="dataSource"/> </bean> <!--事務的配置 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--事務的處理要依賴現有的資料來源 --> <property name="dataSource" ref="dataSource"/> </bean> <!--開啟註解配置事務 --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
5. pojo程式碼<?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:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd "> <!-- 啟用註解 --> <context:annotation-config/> <!--掃描生成單例實體物件 --> <context:component-scan base-package="com.zhq.*"/> <!-- 用於載入連線資料庫的屬性檔案 --> <bean id="preferencesPlaceholderConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="location" value="classpath:config/jdbc.properties"/> </bean> <!--配置資料來源,建立與資料庫的連線池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${driver}"></property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> <!--連線池配置 --> <property name="initialSize" value="${initialSize}"></property> <property name="maxActive" value="${maxActive}"></property> <property name="maxIdle" value="${maxIdle}"></property> <property name="minIdle" value="${minIdle}"></property> </bean> <!--採用Spring提供的Jdbc物件,可以操作資料 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!--配置資料來源物件 --> <constructor-arg ref="dataSource"/> </bean> <!--啟用事務 --> <tx:annotation-driven transaction-manager="transactionManager"/> <!--事務的配置 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--事務的處理要依賴現有的資料來源 --> <property name="dataSource" ref="dataSource"/> </bean> <!--用XML來做事務的配置 --> <aop:config> <!--切入點 --> <aop:pointcut expression="execution(* com.zhq.service.*.*(..))" id="txPoint"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/> </aop:config> <!--事務屬性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!--事務的傳播行為 --> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> </beans>
6. dao程式碼package com.zhq.pojo; import org.springframework.stereotype.Repository; @Repository public class Bank { private int account; private double money; public int getAccount() { return account; } public void setAccount(int account) { this.account = account; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; } @Override public String toString() { return "Bank [account=" + account + ", money=" + money + "]"; } }
package com.zhq.dao;
public interface BankDao {
//根據賬號查詢餘額
public double getMoneyById(String account);
//根據賬號存錢
public void addMoney(String account,double money);
//根據賬號取錢
public void subMoney(String account,double money);
}
package com.zhq.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.zhq.util.MyException;
@Repository
public class BankDaoImpl implements BankDao {
@Autowired
JdbcTemplate jdbcTemplate;
@Override
public double getMoneyById(String account) {
String sql="select money from bank where account=?";
return jdbcTemplate.queryForObject(sql, new Object[] {account}, double.class);
}
@Override
public void addMoney(String account, double money) {
String sql="update bank set money=money+? where account=?";
jdbcTemplate.update(sql, money,account);
}
@Override
public void subMoney(String account, double money) {
double num=getMoneyById(account);//查詢餘額
if(num>money) {//餘額充足,可以取錢
String sql="update bank set money=money-? where account=?";
jdbcTemplate.update(sql, money,account);
}else {//餘額不足,向外丟擲異常
throw new MyException("餘額不足");
}
}
}
7. service 程式碼
package com.zhq.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.zhq.dao.BankDao;
@Repository
public class BankService {
@Autowired
BankDao dao;
@Transactional//如果是XML方式@Transactional不需要
public void transferAccounts(String inAccount,String outAccount,double money) {
dao.addMoney(inAccount, money);
dao.subMoney(outAccount, money);
}
}
8. util程式碼
package com.zhq.util;
/**
* 自定義異常類
* */
public class MyException extends RuntimeException {
public MyException(String msg) {
super(msg);
}
}
9. controller 程式碼
package com.zhq.controller;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zhq.service.BankService;
public class Main {
public static void main(String[] args) {
ApplicationContext cxt=new ClassPathXmlApplicationContext("config/applicationContext.xml");
BankService ser=(BankService) cxt.getBean(BankService.class);
try {
ser.transferAccounts("10001", "10002", 500);
System.out.println("轉賬成功!");
} catch (Exception e) {
System.out.println(e.getMessage()+",轉賬失敗!");
}
}
}
10. 執行效果