一个MVC架构的线程安全的银行转账案例(事务控制)
mvc结构:
准备阶段:jar包 ,dbcpconfig.propertie(数据源配置文件 ) ,DBCPUtil。
jar包:
dbcp配置文件:
- driverClassName=com.mysql.jdbc.Driver
- url=jdbc:mysql://localhost:3306/zhl
- username=root
- password=root
- initialSize=10
- maxActive=50
- maxIdle=20
- minIdle=5
- maxWait=60000
- connectionProperties=useUnicode=true;characterEncoding=utf8
- defaultAutoCommit=true
- defaultReadOnly=
- defaultTransactionIsolation=REPEATABLE_READ
DBCPUti类:
- package com.chensi.test;
- import java.io.InputStream;
- import java.sql.Connection;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- import java.util.Properties;
- import javax.sql.DataSource;
- import org.apache.commons.dbcp.BasicDataSourceFactory;
- public class DBCPUtil {
- private static DataSource ds;
- public static DataSource getDs() {
- return ds;
- }
- public static void setDs(DataSource ds) {
- DBCPUtil.ds = ds;
- }
- static{
- try {
- InputStream in = DBCPUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
- Properties props = new Properties();
- props.load(in);
- ds = BasicDataSourceFactory.createDataSource(props);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static Connection getConnection(){
- try {
- return ds.getConnection();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- }
- public static void release(ResultSet rs,Statement stmt,Connection conn){
- if(rs!=null){
- try {
- rs.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- rs = null;
- }
- if(stmt!=null){
- try {
- stmt.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- stmt = null;
- }
- if(conn!=null){
- try {
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- conn = null;
- }
- }
- }
业务代码:
实体类账户类:
- package com.chensi.domain;
- public class Account {
- private String Id;
- private String name;
- private int money;
- public String getId() {
- return Id;
- }
- public void setId(String id) {
- Id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getMoney() {
- return money;
- }
- public void setMoney(int money) {
- this.money = money;
- }
- @Override
- public String toString() {
- return "Account [Id=" + Id + ", name=" + name + ", money=" + money + "]";
- }
- }
dao层:
- package com.chensi.dao.impl;
- import java.sql.SQLException;
- import org.apache.commons.dbutils.DbUtils;
- import org.apache.commons.dbutils.QueryRunner;
- import org.apache.commons.dbutils.handlers.BeanHandler;
- import com.chensi.dao.TransformDao;
- import com.chensi.domain.Account;
- import com.chensi.test.DBCPUtil;
- import com.chensi.utils.ManagerThreadLocal;
- public class TransformDaoImpl implements TransformDao {
- public Account findAccountByUsername(String username) throws SQLException {
- QueryRunner queryRunner = new QueryRunner(DBCPUtil.getDs());
- Account account = queryRunner.query(ManagerThreadLocal.getConnection(),"select * from Account where name=?", new BeanHandler<Account>(Account.class),username);
- return account;
- }
- public void TransfromMoney(Account account) throws SQLException {
- QueryRunner queryRunner = new QueryRunner(DBCPUtil.getDs());
- queryRunner.update(ManagerThreadLocal.getConnection(),"update account set money=? where name=?",account.getMoney(),account.getName());
- }
- }
service层:
- package com.chensi.service.impl;
- import java.sql.SQLException;
- import com.chensi.dao.TransformDao;
- import com.chensi.dao.impl.TransformDaoImpl;
- import com.chensi.domain.Account;
- import com.chensi.service.TransfromService;
- import com.chensi.utils.ManagerThreadLocal;
- public class TransfromServiceInmpl implements TransfromService {
- TransformDao dao = new TransformDaoImpl();
- //转账的方法
- public void tranFromMoney(String fromUsername, String toUserName, int money) throws SQLException {
- try {
- ManagerThreadLocal.startTransaction();
- Account fromAccount = dao.findAccountByUsername(fromUsername);
- Account toAccount = dao.findAccountByUsername(toUserName);
- fromAccount.setMoney(fromAccount.getMoney()-money);
- toAccount.setMoney(toAccount.getMoney()+money);
- dao.TransfromMoney(toAccount);
- dao.TransfromMoney(fromAccount);
- ManagerThreadLocal.commit();
- } catch (Exception e) {
- ManagerThreadLocal.rollback();
- }finally{
- ManagerThreadLocal.close();
- }
- }
- }
controller层(测试用的,所以写的比较简单):
- package com.chensi.controller;
- import java.sql.SQLException;
- import org.junit.Test;
- import com.chensi.service.TransfromService;
- import com.chensi.service.impl.TransfromServiceInmpl;
- public class TransFromController {
- public static void main(String[] args) throws SQLException {
- TransfromService service = new TransfromServiceInmpl();
- service.tranFromMoney("zhl", "chensi", 200);
- }
- }
控制线程安全的类(自己实现的线程内部类)
- package com.chensi.utils;
- import java.sql.Connection;
- import java.sql.SQLException;
- import com.chensi.test.DBCPUtil;
- //用ThreadLocal线程内部类 来控制 取到的connection是一个线程中的connection,这样可以-
- //安全的控制事务
- public class ManagerThreadLocal {
- private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
- //获取到一个连接 (static 是为了 类名. 调用)
- public static Connection getConnection(){
- Connection conn = tl.get();
- if(conn==null){
- conn = DBCPUtil.getConnection();
- tl.set(conn); //从DBCP线程池中取出一个connn放入到ThreadLocal的Map之中
- }
- return conn;
- }
- //开启事务
- public static void startTransaction(){
- Connection connection = getConnection();
- try {
- connection.setAutoCommit(false); //开启事务 (这个连接是从当前线程取出来的)
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- //提交
- public static void commit(){
- try {
- getConnection().commit(); //提交事务
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- //回滚
- public static void rollback(){
- try {
- getConnection().rollback(); //回滚事务
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- //释放,也即是将conn从ThreadLocal中的Map中移出出去
- public static void close(){
- try {
- getConnection().close(); //连接关闭,然后将threadLocal中的connection 清除
- tl.remove(); //threadLocal(当前线程中清除掉connection)
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
效果:转账前:
转账之后:
一个MVC架构的线程安全的银行转账案例(事务控制)的更多相关文章
- 关于一个mvc架构的cms的后台getshell
都知道,mvc的话 除了根目录还有public目录可以访问,其他的访问都是不行的,因为会默认都是会解析url 然后我们来看今天的猪脚 大概的图片上传还有远程文件加载我黑盒测过了 就是想捞一个快一点的 ...
- 一个初学者对于MVC架构的理解
我很早之前就开始接触.NET开发,一直都在2.0的框架下,所以对于MVC这种架构,听说过,但没有具体使用过,近期和外部朋友接触时,有了解到他们公司在使用MVC这种架构,所以自己就找来相关资料了解一下M ...
- MVC架构学习
作为一名小小的GreenBird,学习MVC呢,已经花费了2天了,期间得到了美丽的学姐的帮助,初步整理了一下. 首先,学习MVC呢就先以一个标准的MVC的简单的例子来入手,然后根据学姐的PPT,我用v ...
- SpringMVC内容略多 有用 熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。
熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构 ...
- RxHttp - 轻量级、可扩展、易使用、完美兼容MVVM、MVC架构的网络封装类库
前言 RxHttp是基于RxJava2+Retrofit 2.9.0+OkHttp 4.9.0实现的轻量级,完美兼容MVVM架构的网络请求封装类库,小巧精致,简单易用,轻轻松松搞定网络请求. GitH ...
- 【JAVA】基于MVC架构Java技术荟萃案例演练
基于JAVA-MVC技术的顾客管理项目案例总结 作者 白宁超 2016年6月9日22:47:08 阅读前瞻:本文源于对javaweb相关技术和资料汇总,涉及大量javaweb基础技术诸如:Servle ...
- Android 四大组件 与 MVC 架构模式
作为一个刚从JAVA转过来的Android程序员总会思考android MVC是什么样的? 首先,我们必须得说Android追寻着MVC架构,那就得先说一下MVC是个啥东西! 总体而来说MVC不能说是 ...
- MVC架构模式分析与设计(一)---简单的mvc架构
首先 我要感谢慕课网的老师提供视频资料 http://www.imooc.com/learn/69 下面我来进行笔记 我们制作一个简单的mvc架构 制作第一个控制器 testController.cl ...
- IntelliMVCCode智能MVC架构的代码助手使用方法
智能代码生成工具,快速帮助开发者提升开发速度,通过工具自动生成MVC架构的大量源代码,节省更多的开发时间. 工具使用的框架:.net4.0,通过工具连接到数据库自动提取数据表或视图中的结构,生成对应的 ...
随机推荐
- 使用Plsql将Excel数据导入Oracle数据库
1.在plsql页面,Tools-->ODBC Importer... 2.配置被导入的excel files 3.选择excel文件 4.选择Excel中要被导入的的sheet工作簿,选择之后 ...
- PIC32MZ tutorial -- External Interrupt
In my older blog "PIC32MZ tutorial -- Key Debounce", I shows how to acheive key debounce w ...
- Android IOS WebRTC 音视频开发总结(八十一)-- WebRTC靠谱吗?有没有适合的SDK推荐?
作者:blaker,最早发表在我们的微信公众和[编风网],详见[这里] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:blackerteam 或 webrtcorgcn) ...
- centos,nginx安装备忘
# ssh 登录慢解决 vim /etc/ssh/sshd_config UseDNS no # add limitsvi /etc/security/limits.conf* soft nproc ...
- template.js遍历对象的写法
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>菜鸟 ...
- 笔试常考的Java基础
1. Socket编程:ServerSocket (int port) :Creates a server socket, bound to the specified port. Socket(In ...
- Openwebrtc
https://github.com/EricssonResearch ============================= webrtc系列不错的博客 http://blog.csdn.net ...
- DataTable自定义排序
使用JQ DataTable 的时候,希望某列数据可以进行自定义排序,操作如下:(以中文排序和百分比排序为例) 1:定义排序类型: //百分率排序 jQuery.fn.dataTableExt.oSo ...
- xargs的原理剖析及用法详解
转载请注明出处:http://www.cnblogs.com/f-ck-need-u/p/5925923.html 学习这个xargs花了很长时间,在网上翻了很久也查了很多书关于xargs的介绍,都只 ...
- jQuery控件有所感悟
两种写法对比: 第一种: ;(function($){ $.fn.myplugin = function(op,params){ if (typeof op == 'string'){ return ...