设为首页收藏本站

安徽论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 11670|回复: 0

mysql+mybatis实现存储过程+事务 + 多并发流水号获取

[复制链接]

83

主题

0

回帖

261

积分

中级会员

Rank: 3Rank: 3

积分
261
发表于 2022-3-26 11:02:42 | 显示全部楼层 |阅读模式
网站内容均来自网络,本站只提供信息平台,如有侵权请联系删除,谢谢!
数据库存储过程
  1. DROP PROCEDURE IF EXISTS `generate_serial_number_by_date`;
  2. CREATE PROCEDURE `generate_serial_number_by_date`(
  3.     IN param_key varchar(100),
  4.     IN param_org_id bigint,
  5.     IN param_period_date_format varchar(20),
  6.       OUT result bigint,
  7.     OUT current_datestr varchar(20))
  8. begin

  9.         declare old_datestr varchar(20);
  10.         
  11.         START TRANSACTION;

  12.         if param_period_date_format='infinite' then
  13.             set current_datestr = '00000000';
  14.     else
  15.             set current_datestr = DATE_FORMAT(NOW(), param_period_date_format);
  16.         end if;
  17.         
  18.         select
  19.                     number, datestr
  20.         from sys_serial_number
  21.         where table_key = param_key
  22.                 and org_id = param_org_id
  23.                 and period_date_format = param_period_date_format
  24.                 into result, old_datestr
  25.                 for update;

  26.         IF result is null then
  27.             
  28.             set result = 1;
  29.             
  30.             insert into sys_serial_number(table_key, org_id, period_date_format, datestr, number, description)
  31.                 values(param_key, param_org_id, param_period_date_format, current_datestr, 1, 'add by procedure');
  32.         
  33.         elseif old_datestr != current_datestr then
  34.             
  35.             set result = 1;
  36.             
  37.             update sys_serial_number
  38.                     set number = 1,   
  39.                             datestr = current_datestr
  40.             where table_key = param_key
  41.                     and org_id = param_org_id
  42.                     and period_date_format = param_period_date_format;
  43.             
  44.         end if;
  45.         
  46.         update sys_serial_number set number = number + 1
  47.             where table_key = param_key
  48.                 and org_id = param_org_id
  49.                 and period_date_format = param_period_date_format;
  50.     commit;
  51. end
复制代码
流水号表
  1. DROP TABLE IF EXISTS `sys_serial_number`;
  2. CREATE TABLE `sys_serial_number` (
  3.   `table_key` varchar(100) NOT NULL COMMENT '主键(建议用表名)',
  4.   `org_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '分公司ID',
  5.   `number` bigint(20) NOT NULL DEFAULT '1' COMMENT '流水号(存储过程控制递增,获取完后+1)',
  6.   `period_date_format` varchar(20) NOT NULL COMMENT '流水号生成周期日期格式',
  7.   `datestr` varchar(20) DEFAULT NULL COMMENT '流水号日期值',
  8.   `description` varchar(100) DEFAULT NULL COMMENT '描述',
  9.   PRIMARY KEY (`table_key`,`org_id`,`period_date_format`)
  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='流水号生成表';
复制代码
mybatis配置
  1. <select id="generateSerialNumber" parameterType="java.util.HashMap" statementType="CALLABLE">
  2.     <![CDATA[
  3.            {
  4.            call generate_serial_number (
  5.             #{param_key,mode=IN,jdbcType=VARCHAR},
  6.             #{param_org_id,mode=IN,jdbcType=BIGINT},
  7.             #{result,mode=OUT,jdbcType=BIGINT}
  8.             )
  9.            }
  10.        ]]>
  11.   </select>
复制代码
测试代码
  1. @Override
  2.     public Map<String, Object> generateSerialNumber(Map<String, Object> param) {
  3.         sysSerialNumberMapper.generateSerialNumber(param);
  4.         return param;
  5.     }
复制代码
  1. final Map<String, Object> param = new HashMap<String, Object>();
  2.         param.put("param_key","contract");
  3.         param.put("param_orgId", 84);
  4.         new Thread(new Runnable() {
  5.             @Override
  6.             public void run() {
  7.                 for(int i =0; i<100; i++) {
  8.                     Map<String, Object> map = serialNumberProvider.generateSerialNumber(param);
  9.                     System.out.println("thread-1:" + map.get("result"));
  10.                 }
  11.             }
  12.         }).start();

  13.         new Thread(new Runnable() {
  14.             @Override
  15.             public void run() {
  16.                 for(int i =0; i<100; i++) {
  17.                     Map<String, Object> map = serialNumberProvider.generateSerialNumber(param);
  18.                     System.out.println("thread-2:" + map.get("result"));
  19.                 }
  20.             }
  21.         }).start();

  22.         new Thread(new Runnable() {
  23.             @Override
  24.             public void run() {
  25.                 for(int i =0; i<100; i++) {
  26.                     Map<String, Object> map = serialNumberProvider.generateSerialNumber(param);
  27.                     System.out.println("thread-3:" + map.get("result"));
  28.                 }
  29.             }
  30.         }).start();

  31.         byte[] b = new byte[0];
  32.         synchronized(b) {
  33.             b.wait();
  34.         }
复制代码
如果运行代码报以下错误
  1. ### SQL: {            call generate_serial_number_by_date (             ?,             ?,             ?,             ?,             ?            )            }### Cause: java.sql.SQLException: Parameter number 4 is not an OUT parameter; SQL []; Parameter number 4 is not an OUT parameter; nested exception is java.sql.SQLException: Parameter number 4 is not an OUT parameter
复制代码
排查方法:
1、检查存储过程是否正确创建
2、检查数据源连接用户是否有存储过程执行权限
到此这篇关于mysql+mybatis实现存储过程+事务 + 多并发流水号获取的文章就介绍到这了,更多相关mysql mybatis存储过程流水号内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
                                                        
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
免责声明
1. 本论坛所提供的信息均来自网络,本网站只提供平台服务,所有账号发表的言论与本网站无关。
2. 其他单位或个人在使用、转载或引用本文时,必须事先获得该帖子作者和本人的同意。
3. 本帖部分内容转载自其他媒体,但并不代表本人赞同其观点和对其真实性负责。
4. 如有侵权,请立即联系,本网站将及时删除相关内容。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表