Spring 框架實現(xiàn)賬戶轉(zhuǎn)賬功能(推薦)
一、引言
在企業(yè)級應(yīng)用開發(fā)中,事務(wù)管理是非常重要的一部分。例如在銀行轉(zhuǎn)賬業(yè)務(wù)中,需要保證付款和收款操作要么同時成功,要么同時失敗,以確保數(shù)據(jù)的一致性和完整性。Spring 框架為我們提供了強大的事務(wù)管理功能,本文將詳細介紹如何使用 Spring 框架實現(xiàn)一個簡單的賬戶轉(zhuǎn)賬功能,并對相關(guān)代碼進行深入解析。
二、項目整體架構(gòu)
本項目主要包含服務(wù)層、數(shù)據(jù)訪問層、配置類和測試類,通過 Spring 框架的依賴注入和事務(wù)管理功能,實現(xiàn)賬戶轉(zhuǎn)賬的業(yè)務(wù)邏輯。下面是項目中各個文件的主要作用:
- AccountService.java:定義轉(zhuǎn)賬服務(wù)的接口。
- AccountDao.java 和 AccountDaoImpl.java:數(shù)據(jù)訪問層,負責(zé)數(shù)據(jù)庫的增刪改查操作。
- AccountServiceImpl.java:實現(xiàn)轉(zhuǎn)賬服務(wù)的具體邏輯。
- TransactionConfig.java 和 AppConfig.java:配置類,用于配置數(shù)據(jù)源、事務(wù)管理器等。
- Test.java:測試類,用于測試轉(zhuǎn)賬功能。
三、代碼詳細解析
1. 服務(wù)層接口 AccountService.java
package com.qcby.service; public interface AccountService { /** * 轉(zhuǎn)賬的方式 * @param out 付款人 * @param in 收款人 * @param money 金額 */ public void pay(String out,String in, double money); }
該接口定義了一個 pay
方法,用于實現(xiàn)轉(zhuǎn)賬功能,接收付款人、收款人姓名和轉(zhuǎ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. 服務(wù)層實現(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
注解將該類標(biāo)記為服務(wù)層組件,使用 @Transactional
注解開啟事務(wù)管理,保證 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//啟動注解驅(qū)動的事務(wù)管理 public class TransactionConfig { @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
配置事務(wù)管理器,使用 @EnableTransactionManagement
注解開啟注解驅(qū)動的事務(wù)管理。
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})//導(dǎo)入事務(wù)配置 @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
和事務(wù)管理器,使用 @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; } }
四、總結(jié)
通過本文的介紹,我們了解了如何使用 Spring 框架實現(xiàn)一個簡單的賬戶轉(zhuǎn)賬功能。主要使用了 Spring 的依賴注入、JdbcTemplate
和事務(wù)管理功能,保證了轉(zhuǎn)賬操作的原子性和數(shù)據(jù)的一致性。在實際開發(fā)中,我們可以根據(jù)具體需求對代碼進行擴展和優(yōu)化,例如添加更多的業(yè)務(wù)邏輯和異常處理。
希望本文對大家理解 Spring 框架的事務(wù)管理和數(shù)據(jù)庫操作有所幫助。如果你有任何問題或建議,歡迎在評論區(qū)留言。
到此這篇關(guān)于Spring 框架實現(xiàn)賬戶轉(zhuǎn)賬功能全解析的文章就介紹到這了,更多相關(guān)Spring賬戶轉(zhuǎn)賬內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
classloader類加載器_基于java類的加載方式詳解
下面小編就為大家?guī)硪黄猚lassloader類加載器_基于java類的加載方式詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10Java?Runnable和Thread實現(xiàn)多線程哪個更好你知道嗎
這篇文章主要為大家詳細介紹了Java?Runnable和Thread實現(xiàn)多線程哪個更好,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助<BR>2022-03-03使用webservice自定義注解處理參數(shù)加解密問題
這篇文章主要介紹了使用webservice自定義注解處理參數(shù)加解密問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12Spring?Boot實現(xiàn)登錄驗證碼功能的案例詳解
驗證碼的作用可以有效防止其他人對某一個特定的注冊用戶用特定的程序暴力破解方式進行不斷的登錄嘗試,接下來通過本文給大家介紹Spring?Boot實現(xiàn)登錄驗證碼功能,需要的朋友可以參考下2022-08-08javaWeb用戶權(quán)限控制簡單實現(xiàn)過程
這篇文章主要為大家詳細介紹了javaWeb用戶權(quán)限控制簡單實現(xiàn)過程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-08-08Spring Boot和Thymeleaf整合結(jié)合JPA實現(xiàn)分頁效果(實例代碼)
這篇文章主要介紹了Spring Boot和Thymeleaf整合結(jié)合JPA實現(xiàn)分頁效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02