日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

淺談mybatis 樂(lè)觀鎖實(shí)現(xiàn),解決并發(fā)問(wèn)題

瀏覽:215日期:2023-10-23 10:11:45

情景展示:

銀行兩操作員同時(shí)操作同一賬戶就是典型的例子。

比如A、B操作員同時(shí)讀取一余額為1000元的賬戶,A操作員為該賬戶增加100元,B操作員同時(shí)為該賬戶扣除50元,A先提交,B后提交。最后實(shí)際賬戶余額為1000-50=950元,但本該為1000+100-50=1050。這就是典型的并發(fā)問(wèn)題。

樂(lè)觀鎖機(jī)制在一定程度上解決了這個(gè)問(wèn)題。樂(lè)觀鎖,大多是基于數(shù)據(jù)版本(Version)記錄機(jī)制實(shí)現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),在基于數(shù)據(jù)庫(kù)表的版本解決方案中,一般是通過(guò)為數(shù)據(jù)庫(kù)表增加一個(gè) “version” 字段來(lái)實(shí)現(xiàn)。

讀取出數(shù)據(jù)時(shí),將此版本號(hào)一同讀出,之后更新時(shí),對(duì)此版本號(hào)加一。此時(shí),將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對(duì),如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過(guò)期數(shù)據(jù)。

對(duì)于上面修改用戶帳戶信息的例子而言,假設(shè)數(shù)據(jù)庫(kù)中帳戶信息表中有一個(gè)version字段,當(dāng)前值為1;而當(dāng)前帳戶余額字段(balance)為1000元。假設(shè)操作員A先更新完,操作員B后更新。

a、操作員A此時(shí)將其讀出(version=1),并從其帳戶余額中增加100(1000+100=1100)。

b、在操作員A操作的過(guò)程中,操作員B也讀入此用戶信息(version=1),并從其帳戶余額中扣除50(1000-50=950)。

c、操作員A完成了修改工作,將數(shù)據(jù)版本號(hào)加一(version=2),連同帳戶增加后余額(balance=1100),提交至數(shù)據(jù)庫(kù)更新,此時(shí)由于提交數(shù)據(jù)版本大于數(shù)據(jù)庫(kù)記錄當(dāng)前版本,數(shù)據(jù)被更新,數(shù)據(jù)庫(kù)記錄version更新為2。

d、操作員B完成了操作,也將版本號(hào)加一(version=2)試圖向數(shù)據(jù)庫(kù)提交數(shù)據(jù)(balance=950),但此時(shí)比對(duì)數(shù)據(jù)庫(kù)記錄版本時(shí)發(fā)現(xiàn),操作員B提交的數(shù)據(jù)版本號(hào)為2,數(shù)據(jù)庫(kù)記錄當(dāng)前版本也為2,不滿足 “提交版本必須大于記錄當(dāng)前版本才能執(zhí)行更新 “的樂(lè)觀鎖策略,因此,操作員B的提交被駁回。

這樣,就避免了操作員B用基于version=1的舊數(shù)據(jù)修改的結(jié)果覆蓋操作員A的操作結(jié)果的可能。

示例代碼:

account建庫(kù)腳本

drop table if exists account_wallet; /*==============================================================*//* Table: account_wallet *//*==============================================================*/create table account_wallet( id int not null comment ’用戶錢(qián)包主鍵’, user_open_id varchar(64) comment ’用戶中心的用戶唯一編號(hào)’, user_amount decimal(10,5), create_time datetime, update_time datetime, pay_password varchar(64), is_open int comment ’0:代表未開(kāi)啟支付密碼,1:代表開(kāi)發(fā)支付密碼’, check_key varchar(64) comment ’平臺(tái)進(jìn)行用戶余額更改時(shí),首先效驗(yàn)key值,否則無(wú)法進(jìn)行用戶余額更改操作’, version int comment ’基于mysql樂(lè)觀鎖,解決并發(fā)訪問(wèn)’ primary key (id));

dao層

AccountWallet selectByOpenId(String openId);

int updateAccountWallet(AccountWallet record);

service 層

AccountWallet selectByOpenId(String openId);

int updateAccountWallet(AccountWallet record);

serviceImpl層

public AccountWallet selectByOpenId(String openId) { // TODO Auto-generated method stub return accountWalletMapper.selectByOpenId(openId); } public int updateAccountWallet(AccountWallet record) { // TODO Auto-generated method stub return accountWalletMapper.updateAccountWallet(record); }

sql.xml

<!--通過(guò)用戶唯一編號(hào),查詢用戶錢(qián)包相關(guān)的信息 --> <select resultMap='BaseResultMap' parameterType='java.lang.String'> select <include refid='Base_Column_List' /> from account_wallet where user_open_id = #{openId,jdbcType=VARCHAR} </select> <!--用戶錢(qián)包數(shù)據(jù)更改 ,通過(guò)樂(lè)觀鎖(version機(jī)制)實(shí)現(xiàn) --> <update parameterType='com.settlement.model.AccountWallet'> <![CDATA[ update account_wallet set user_amount = #{userAmount,jdbcType=DECIMAL}, version = version + 1 where id =#{id,jdbcType=INTEGER} and version = #{version,jdbcType=INTEGER} ]]> </update>

controller 層

package com.settlement.controller; import java.math.BigDecimal;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import com.settlement.commons.base.BaseController;import com.settlement.model.AccountWallet;import com.settlement.service.AccountWalletService;import com.taobao.api.internal.util.StringUtils; /** * 用戶錢(qián)包Controller * * @author zzg * @date 2017-02-10 */ @Controller@RequestMapping(value = '/wallet')public class WalletController extends BaseController { @Autowiredprivate AccountWalletService accountWalletService; /** * 針對(duì)業(yè)務(wù)系統(tǒng)高并發(fā)-----修改用戶錢(qián)包數(shù)據(jù)余額,采用樂(lè)觀鎖 * * @return */@RequestMapping(value = '/walleroptimisticlock.action', method = RequestMethod.POST)@ResponseBodypublic String walleroptimisticlock(HttpServletRequest request) { String result = ''; try {String openId = request.getParameter('openId') == null ? null: request.getParameter('openId').trim(); // 用戶唯一編號(hào)String openType = request.getParameter('openType') == null ? null: request.getParameter('openType').trim(); // 1:代表增加,2:代表減少String amount = request.getParameter('amount') == null ? null: request.getParameter('amount').trim(); // 金額 if (StringUtils.isEmpty(openId)) {return 'openId is null';}if (StringUtils.isEmpty(openType)) {return 'openType is null';}if (StringUtils.isEmpty(amount)) {return 'amount is null';}AccountWallet wallet = accountWalletService.selectByOpenId(openId); // 用戶操作金額BigDecimal cash = BigDecimal.valueOf(Double.parseDouble(amount));cash.doubleValue();cash.floatValue();if (Integer.parseInt(openType) == 1) {wallet.setUserAmount(wallet.getUserAmount().add(cash));} else if (Integer.parseInt(openType) == 2) {wallet.setUserAmount(wallet.getUserAmount().subtract(cash));} int target = accountWalletService.updateAccountWallet(wallet);System.out.println('修改用戶金額是否:' + (target == 1 ? '成功' : '失敗')); } catch (Exception e) {result = e.getMessage();return result;} return 'success';} }

模擬并發(fā)訪問(wèn)

package com.settlement.concurrent; import java.text.SimpleDateFormat;import java.util.Date;import java.util.concurrent.CountDownLatch; import com.settlement.commons.utils.HttpRequest; /** * 模擬用戶的并發(fā)請(qǐng)求,檢測(cè)用戶樂(lè)觀鎖的性能問(wèn)題 * * @author zzg * @date 2017-02-10 */public class ConcurrentTest {final static SimpleDateFormat sdf=new SimpleDateFormat('yyyy-MM-dd HH:mm:ss'); public static void main(String[] args){CountDownLatch latch=new CountDownLatch(1);//模擬5人并發(fā)請(qǐng)求,用戶錢(qián)包for(int i=0;i<5;i++){//模擬5個(gè)用戶AnalogUser analogUser = new AnalogUser('user'+i,'58899dcd-46b0-4b16-82df-bdfd0d953bfb','1','20.024',latch);analogUser.start();}latch.countDown();//計(jì)數(shù)器?p一 所有線程釋放 并發(fā)訪問(wèn)。System.out.println('所有模擬請(qǐng)求結(jié)束 at '+sdf.format(new Date())); }static class AnalogUser extends Thread{String workerName;//模擬用戶姓名String openId;String openType;String amount;CountDownLatch latch;public AnalogUser(String workerName, String openId, String openType, String amount,CountDownLatch latch) {super();this.workerName = workerName;this.openId = openId;this.openType = openType;this.amount = amount;this.latch = latch;}@Overridepublic void run() {// TODO Auto-generated method stubtry { latch.await(); //一直阻塞當(dāng)前線程,直到計(jì)時(shí)器的值為0 } catch (InterruptedException e) { e.printStackTrace(); } post();//發(fā)送post 請(qǐng)求 } public void post(){String result = '';System.out.println('模擬用戶: '+workerName+' 開(kāi)始發(fā)送模擬請(qǐng)求 at '+sdf.format(new Date())); result = HttpRequest.sendPost('http://localhost:8080/Settlement/wallet/walleroptimisticlock.action', 'openId='+openId+'&openType='+openType+'&amount='+amount);System.out.println('操作結(jié)果:'+result);System.out.println('模擬用戶: '+workerName+' 模擬請(qǐng)求結(jié)束 at '+sdf.format(new Date())); }}}

補(bǔ)充知識(shí):Mybatis-plus代碼生成器,自用版本不帶xml

package com.wuyd.mybatispulsdemo;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.generator.AutoGenerator;import com.baomidou.mybatisplus.generator.config.*;import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;/** * @author wuyd * 創(chuàng)建時(shí)間:2019/10/8 11:17 */public class CodeGenerator { public static void main(String[] args) { AutoGenerator mpg = new AutoGenerator(); //全局配置 GlobalConfig gc = new GlobalConfig(); gc.setOutputDir(System.getProperty('user.dir')+'/src/main/java'); gc.setFileOverride(true); //不需要ActiveRecord特性的請(qǐng)改為false gc.setActiveRecord(true); gc.setSwagger2(true); gc.setAuthor('wuyd'); //自定義文件命名,注意%s 會(huì)自動(dòng)填充表實(shí)體屬性 gc.setControllerName('%sController'); gc.setServiceName('%sService'); gc.setServiceImplName('%sServiceImpl'); gc.setEntityName('%sEntity'); gc.setMapperName('%sMapper'); mpg.setGlobalConfig(gc); //數(shù)據(jù)源配置 DataSourceConfig dsc = new DataSourceConfig(); dsc.setDbType(DbType.MYSQL); dsc.setDriverName('com.mysql.jdbc.Driver'); dsc.setUsername('xxx'); dsc.setPassword('xxx'); dsc.setUrl('jdbc:mysql://xxx.xxx.xxx.xxx:3306/xxxxx?useUnicode=true&useSSL=false&characterEncoding=utf8'); mpg.setDataSource(dsc); //策略配置 StrategyConfig strategy = new StrategyConfig(); //此處可以修改您的表前綴 strategy.setTablePrefix(new String[]{}); //表名生成策略 strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); //需要生成的表 strategy.setInclude(new String[]{'knapsacks','knapsacks_kind','knapsacks_prop','knapsacks_recharge_card'}); strategy.setSuperServiceClass(null); strategy.setSuperServiceImplClass(null); strategy.setSuperMapperClass(null); strategy.setControllerMappingHyphenStyle(true); strategy.setEntityLombokModel(true); strategy.setEntitySerialVersionUID(true); strategy.setEntityTableFieldAnnotationEnable(true); mpg.setStrategy(strategy); // 配置模板 TemplateConfig templateConfig = new TemplateConfig(); templateConfig.setXml(null); mpg.setTemplate(templateConfig); //包配置 PackageConfig pc = new PackageConfig(); pc.setParent('com.wuyd.mybatispulsdemo'); pc.setController('controller'); pc.setService('service'); pc.setServiceImpl('service.impl'); pc.setMapper('mapper'); pc.setEntity('entity'); mpg.setPackageInfo(pc); //執(zhí)行生成 mpg.execute(); }}

pom.xml

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.2.0</version> </dependency> <!-- ORM 選一款 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus-boot-starter.version}</version> </dependency> <!-- Mysql驅(qū)動(dòng) 注意版本!--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector.version}</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.1</version> </dependency>

參考列表

官網(wǎng)代碼生成器部分

以上這篇淺談mybatis 樂(lè)觀鎖實(shí)現(xiàn),解決并發(fā)問(wèn)題就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。

日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
午夜在线一区二区| 国产日韩1区| 精品不卡一区| 国产精品白浆| 欧美激情日韩| 精品久久久网| 国产91欧美| 伊人久久在线| 99久久精品国产亚洲精品| 99久久亚洲精品蜜臀| 国户精品久久久久久久久久久不卡| 99精品网站| 久久精品官网| 日韩欧美美女在线观看| 青青国产精品| 欧美日韩精品在线一区| 亚洲综合色婷婷在线观看| а√在线中文在线新版| 免费在线亚洲欧美| 亚洲高清激情| 午夜免费一区| 日韩av黄色在线| 国产毛片精品久久| 蜜桃视频在线观看一区二区| 欧美精品三级在线| 国产精品99久久免费| av中文资源在线资源免费观看| 91偷拍一区二区三区精品| 久久久天天操| 欧美中文字幕一区二区| 亚洲主播在线| 国产精区一区二区| 国产成人精品一区二区三区在线| 色88888久久久久久影院| 亚洲欧美高清| 国产亚洲一区二区三区啪| 成人在线超碰| 99综合视频| 国产精品日本一区二区不卡视频| 国产美女高潮在线观看| 在线亚洲一区| 国产日韩欧美三级| 欧美成人基地 | 丝袜a∨在线一区二区三区不卡| 日韩免费精品| 日本一区二区免费高清| 99热免费精品| 久久久久久亚洲精品美女| 激情婷婷亚洲| 国产欧美一区二区三区国产幕精品| 日本欧美国产| 亚洲日产av中文字幕| 精品久久久网| 国产精品女主播一区二区三区| 国产乱码精品一区二区三区亚洲人| 日韩国产欧美一区二区| 视频在线观看国产精品| 久久亚洲黄色| 一区二区亚洲视频| 中文字幕色婷婷在线视频| 久久先锋影音| 岛国av在线播放| 日韩综合小视频| 久久久精品五月天| 国产欧美一区二区色老头| 欧美国产91| 欧美aa在线视频| 久久福利影视| 日韩电影在线视频| 国产欧美精品| 9色国产精品| 亚洲黄色免费看| 青青国产精品| 丝袜亚洲另类欧美| 欧美成人精品三级网站| 国产精品久久久久久av公交车| 午夜日本精品| 涩涩av在线| 国产精品综合| 一区二区国产在线| 伊人精品一区| 久久久久久网| 亚洲人成亚洲精品| 麻豆精品蜜桃| 国产91在线播放精品| 久久精品超碰| 亚洲精选91| 在线视频日韩| 日韩欧美看国产| 精品久久久网| 国产精品一区2区3区| 亚洲欧洲av| 日韩一级不卡| 激情久久五月| 日韩在线短视频| 国产va免费精品观看精品视频| 国产欧美一级| 日本va欧美va瓶| 樱桃成人精品视频在线播放| 亚洲黄色免费av| 成人污污视频| 久久97视频| 国产精品一区二区精品视频观看| 亚洲影视一区| 丝袜国产日韩另类美女| 黄色欧美日韩| 久久久久亚洲| 蜜桃精品在线| 电影天堂国产精品| 中文字幕在线官网| 视频在线不卡免费观看| 精品无人区麻豆乱码久久久| 国产欧美在线观看免费| 国产真实久久| 欧美亚洲激情| 婷婷中文字幕一区| 婷婷激情综合| 在线视频日韩| 99国产成+人+综合+亚洲欧美| 日韩精品看片| 激情久久婷婷| 午夜日韩福利| 日韩中文字幕麻豆| 免费成人在线观看| 亚洲免费福利一区| 日韩av网站在线免费观看| 日韩国产欧美一区二区三区| 91精品国产经典在线观看| 亚洲精品国产精品粉嫩| 亚洲精品成a人ⅴ香蕉片| 免费一级片91| 日本国产亚洲| 国产精品亚洲一区二区在线观看 | 日本 国产 欧美色综合| 蜜桃久久久久久| 婷婷精品在线观看| 国产日韩视频在线| 麻豆成人91精品二区三区| 成人一区而且| 久久激情中文| 一区二区亚洲精品| 黄色欧美日韩| 亚洲开心激情| 国产福利一区二区精品秒拍 | 97国产成人高清在线观看| 岛国av在线网站| 亚洲欧美综合| 在线综合亚洲| 日本成人手机在线| 免费精品一区| 播放一区二区| 香蕉国产精品| 最新国产精品视频| 国产精品1luya在线播放| 国产精品99一区二区三| 一区二区三区四区在线看| 日本欧洲一区二区| 国产精品嫩草影院在线看| 亚洲深夜视频| 国产视频一区三区| 欧美私人啪啪vps| 免费看av不卡| 视频一区二区中文字幕| 国产精品视频首页| 日韩在线观看不卡| 在线精品视频一区| 国产精品亚洲片在线播放| 日韩欧美中文| 蜜桃视频免费观看一区| 久久不见久久见免费视频7| 成人福利av| 在线看片一区| 精品国产亚洲一区二区在线观看| 亚洲天堂久久| 国产日产精品_国产精品毛片 | 91麻豆精品激情在线观看最新| 激情久久一区二区| 亚洲一区日韩| 久久亚洲国产精品尤物| 一区视频在线| 国产精品一区三区在线观看| 久久婷婷激情| 欧美色综合网| 中文av在线全新| 亚洲精品第一| 91精品国产调教在线观看| 日本视频在线一区| 日韩在线视频精品| 在线视频亚洲欧美中文| 精品视频97| 蜜桃一区二区三区在线| 91视频一区| 欧美日韩视频免费看| 蜜桃国内精品久久久久软件9| 人人爱人人干婷婷丁香亚洲| 婷婷综合六月| 国产日本亚洲| 午夜在线精品| 亚洲爱爱视频| 国产精品久久久久久久久免费高清 |