一、引言
在企业级应用开发中,事务管理是非常重要的一部分。例如在银行转账业务中,需要保证付款和收款操作要么同时成功,要么同时失败,以确保数据的一致性和完整性。spring 框架为我们提供了强大的事务管理功能,本文将详细介绍如何使用 spring 框架实现一个简单的账户转账功能,并对相关代码进行深入解析。
二、项目整体架构
本项目主要包含服务层、数据访问层、配置类和测试类,通过 spring 框架的依赖注入和事务管理功能,实现账户转账的业务逻辑。下面是项目中各个文件的主要作用:
- accountservice.java:定义转账服务的接口。
- accountdao.java 和 accountdaoimpl.java:数据访问层,负责数据库的增删改查操作。
- accountserviceimpl.java:实现转账服务的具体逻辑。
- transactionconfig.java 和 appconfig.java:配置类,用于配置数据源、事务管理器等。
- 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
方法,用于实现转账功能,接收付款人、收款人姓名和转账金额作为参数。
2. 数据访问层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
来执行 sql 语句,实现了 accountdao
接口中的两个方法。
3. 服务层实现类 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); } }
配置数据源、jdbctemplate
和事务管理器,使用 @propertysource
注解加载数据库配置文件。
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); //完成數據增刪改查 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>{ /** *是一行一行进行数据封装的 *@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 框架实现一个简单的账户转账功能。主要使用了 spring 的依赖注入、jdbctemplate
和事务管理功能,保证了转账操作的原子性和数据的一致性。在实际开发中,我们可以根据具体需求对代码进行扩展和优化,例如添加更多的业务逻辑和异常处理。
希望本文对大家理解 spring 框架的事务管理和数据库操作有所帮助。如果你有任何问题或建议,欢迎在评论区留言。
到此这篇关于spring 框架实现账户转账功能全解析的文章就介绍到这了,更多相关spring账户转账内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论