Spring 框架實現(xiàn)賬戶轉賬功能(推薦)
一、引言
在企業(yè)級應用開發(fā)中,事務管理是非常重要的一部分。例如在銀行轉賬業(yè)務中,需要保證付款和收款操作要么同時成功,要么同時失敗,以確保數(shù)據(jù)的一致性和完整性。Spring 框架為我們提供了強大的事務管理功能,本文將詳細介紹如何使用 Spring 框架實現(xiàn)一個簡單的賬戶轉賬功能,并對相關代碼進行深入解析。
二、項目整體架構
本項目主要包含服務層、數(shù)據(jù)訪問層、配置類和測試類,通過 Spring 框架的依賴注入和事務管理功能,實現(xiàn)賬戶轉賬的業(yè)務邏輯。下面是項目中各個文件的主要作用:
- AccountService.java:定義轉賬服務的接口。
- AccountDao.java 和 AccountDaoImpl.java:數(shù)據(jù)訪問層,負責數(shù)據(jù)庫的增刪改查操作。
- AccountServiceImpl.java:實現(xiàn)轉賬服務的具體邏輯。
- TransactionConfig.java 和 AppConfig.java:配置類,用于配置數(shù)據(jù)源、事務管理器等。
- Test.java:測試類,用于測試轉賬功能。
三、代碼詳細解析
1. 服務層接口 AccountService.java
package com.qcby.service;
public interface AccountService {
/**
* 轉賬的方式
* @param out 付款人
* @param in 收款人
* @param money 金額
*/
public void pay(String out,String in, double money);
}該接口定義了一個 pay 方法,用于實現(xiàn)轉賬功能,接收付款人、收款人姓名和轉賬金額作為參數(shù)。
2. 數(shù)據(jù)訪問層AccountDao.java和 AccountDaoImpl.java
AccountDao.java
package com.qcby.dao;
public interface AccountDao {
void outMoney(String out,double money);
void inMoney(String in,double money);
}定義了兩個方法,outMoney 用于從付款人賬戶扣除金額,inMoney 用于向收款人賬戶增加金額。
AccountDaoImpl.java
package com.qcby.dao.Impl;
import com.qcby.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void outMoney(String out,double money) {
jdbcTemplate.update("update account set money=money-? where name=?",money,out);
}
@Override
public void inMoney(String in,double money) {
jdbcTemplate.update("update account set money=money+? where name=?",money,in);
}
}使用 Spring 的 JdbcTemplate 來執(zhí)行 SQL 語句,實現(xiàn)了 AccountDao 接口中的兩個方法。
3. 服務層實現(xiàn)類 AccountServiceImpl.java
package com.qcby.service.impl;
import com.qcby.dao.AccountDao;
import com.qcby.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional(
isolation = Isolation.DEFAULT,
propagation = Propagation.REQUIRED
)
@Override
public void pay(String out,String in, double money) {
accountDao.outMoney(out,money);
accountDao.inMoney(in,money);
}
}使用 @Service 注解將該類標記為服務層組件,使用 @Transactional 注解開啟事務管理,保證 pay 方法中的 outMoney 和 inMoney 操作要么同時成功,要么同時失敗。
4. 配置類 TransactionConfig.java 和 AppConfig.java
TransactionConfig.java
package com.qcby.Utils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement//啟動注解驅動的事務管理
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}配置事務管理器,使用 @EnableTransactionManagement 注解開啟注解驅動的事務管理。
AppConfig.java
package com.qcby.Utils;
import com.qcby.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@PropertySource("classpath:jdbc.properties")
@Import({TransactionConfig.class})//導入事務配置
@EnableAspectJAutoProxy(proxyTargetClass=true)
@EnableTransactionManagement
public class AppConfig {
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
} 配置數(shù)據(jù)源、JdbcTemplate 和事務管理器,使用 @PropertySource 注解加載數(shù)據(jù)庫配置文件。
5. 測試類 Test.java
import com.qcby.Utils.AppConfig;
import com.qcby.Utils.UserProxy;
import com.qcby.entity.Account;
import com.qcby.service.AccountService;
import com.qcby.service.UserService;
import com.qcby.service.impl.UserServiceImpl;
import org.aspectj.lang.annotation.Around;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppConfig.class, UserProxy.class})
public class Test {
@org.junit.Test
public void test() {
ApplicationContext context = new AnnotationConfigApplicationContext(UserProxy.class);
UserService userService = (UserService) context.getBean("userserviceimpl");
userService.save();
}
@org.junit.Test
public void test2() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
dataSource.setUsername("root");
dataSource.setPassword("123456");
JdbcTemplate template = new JdbcTemplate(dataSource);
//完成數(shù)據(jù)增刪改查
template.update("insert into account values (null,?,?)","熊er",2000);
}
@Autowired
private JdbcTemplate jdbcTemplate;
@org.junit.Test
public void test3() {
jdbcTemplate.update("insert into account values (null,?,?) ","翠花",200000);
}
@org.junit.Test
public void test4() {
jdbcTemplate.update("update account set name=? where money=?",new Object[]{"光頭強",200000});
}
@org.junit.Test
public void test5() {
List<Account> list = jdbcTemplate.query("select * from account",new BeanMapper());
for (Account account : list) {
System.out.println(account);
}
}
@org.junit.Test
public void Pay() {
String out = "熊大";
String in="熊er";
double money=500;
ApplicationContext context =new ClassPathXmlApplicationContext("Spring.xml");
AccountService accountService = (AccountService) context.getBean("accountService");
accountService.pay(out,in,money);
}
@org.junit.Test
public void test6() {
ApplicationContext context =new AnnotationConfigApplicationContext(UserProxy.class);
AccountService accountService = (AccountService) context.getBean(AccountService.class);
accountService.pay("熊大","熊er",100);
}
}
class BeanMapper implements RowMapper<Account>{
/**
*是一行一行進行數(shù)據(jù)封裝的
*@paramresultSet
*@parami
*@return
*@throwsSQLException
*/
@Override
public Account mapRow(ResultSet resultSet, int i)throws
SQLException{
Account account=new Account();
account.setId(resultSet.getInt("id"));
account.setName(resultSet.getString("name"));
account.setMoney(resultSet.getDouble("money"));
return account;
}
}四、總結
通過本文的介紹,我們了解了如何使用 Spring 框架實現(xiàn)一個簡單的賬戶轉賬功能。主要使用了 Spring 的依賴注入、JdbcTemplate 和事務管理功能,保證了轉賬操作的原子性和數(shù)據(jù)的一致性。在實際開發(fā)中,我們可以根據(jù)具體需求對代碼進行擴展和優(yōu)化,例如添加更多的業(yè)務邏輯和異常處理。
希望本文對大家理解 Spring 框架的事務管理和數(shù)據(jù)庫操作有所幫助。如果你有任何問題或建議,歡迎在評論區(qū)留言。
到此這篇關于Spring 框架實現(xiàn)賬戶轉賬功能全解析的文章就介紹到這了,更多相關Spring賬戶轉賬內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
classloader類加載器_基于java類的加載方式詳解
下面小編就為大家?guī)硪黄猚lassloader類加載器_基于java類的加載方式詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
Java?Runnable和Thread實現(xiàn)多線程哪個更好你知道嗎
這篇文章主要為大家詳細介紹了Java?Runnable和Thread實現(xiàn)多線程哪個更好,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助<BR>2022-03-03
使用webservice自定義注解處理參數(shù)加解密問題
這篇文章主要介紹了使用webservice自定義注解處理參數(shù)加解密問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
Spring?Boot實現(xiàn)登錄驗證碼功能的案例詳解
驗證碼的作用可以有效防止其他人對某一個特定的注冊用戶用特定的程序暴力破解方式進行不斷的登錄嘗試,接下來通過本文給大家介紹Spring?Boot實現(xiàn)登錄驗證碼功能,需要的朋友可以參考下2022-08-08
Spring Boot和Thymeleaf整合結合JPA實現(xiàn)分頁效果(實例代碼)
這篇文章主要介紹了Spring Boot和Thymeleaf整合結合JPA實現(xiàn)分頁效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02

