欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-17 09:05:13
数据库存储过程drop procedure if exists `generate_serial_number_by_date`;create procedure `generate_serial_n...

数据库存储过程

drop procedure if exists `generate_serial_number_by_date`;
create procedure `generate_serial_number_by_date`(
    in param_key varchar(100),
    in param_org_id bigint, 
    in param_period_date_format varchar(20), 
      out result bigint,
    out current_datestr varchar(20))
begin 

        declare old_datestr varchar(20);
        
        start transaction; 

        if param_period_date_format='infinite' then 
            set current_datestr = '00000000';
    else
            set current_datestr = date_format(now(), param_period_date_format);
        end if;
        
        select 
                    number, datestr 
        from sys_serial_number
        where table_key = param_key 
                and org_id = param_org_id 
                and period_date_format = param_period_date_format
                into result, old_datestr
                for update;

        if result is null then
            
            set result = 1;
            
            insert into sys_serial_number(table_key, org_id, period_date_format, datestr, number, description) 
                values(param_key, param_org_id, param_period_date_format, current_datestr, 1, 'add by procedure');
        
        elseif old_datestr != current_datestr then
            
            set result = 1;
            
            update sys_serial_number 
                    set number = 1,    
                            datestr = current_datestr 
            where table_key = param_key 
                    and org_id = param_org_id 
                    and period_date_format = param_period_date_format;
            
        end if;
        
        update sys_serial_number set number = number + 1 
            where table_key = param_key 
                and org_id = param_org_id 
                and period_date_format = param_period_date_format;
    commit;
end

流水号表

drop table if exists `sys_serial_number`;
create table `sys_serial_number` (
  `table_key` varchar(100) not null comment '主键(建议用表名)',
  `org_id` bigint(20) not null default '0' comment '分公司id',
  `number` bigint(20) not null default '1' comment '流水号(存储过程控制递增,获取完后+1)',
  `period_date_format` varchar(20) not null comment '流水号生成周期日期格式',
  `datestr` varchar(20) default null comment '流水号日期值',
  `description` varchar(100) default null comment '描述',
  primary key (`table_key`,`org_id`,`period_date_format`)
) engine=innodb default charset=utf8 row_format=dynamic comment='流水号生成表';

mybatis配置

<select id="generateserialnumber" parametertype="java.util.hashmap" statementtype="callable">
    <![cdata[
           {
           call generate_serial_number (
            #{param_key,mode=in,jdbctype=varchar},
            #{param_org_id,mode=in,jdbctype=bigint},
            #{result,mode=out,jdbctype=bigint}
            )
           }
       ]]>
  </select>

 

测试代码

@override
    public map<string, object> generateserialnumber(map<string, object> param) {
        sysserialnumbermapper.generateserialnumber(param);
        return param;
    }
final map<string, object> param = new hashmap<string, object>();
        param.put("param_key","contract");
        param.put("param_orgid", 84);
        new thread(new runnable() {
            @override
            public void run() {
                for(int i =0; i<100; i++) {
                    map<string, object> map = serialnumberprovider.generateserialnumber(param);
                    system.out.println("thread-1:" + map.get("result"));
                }
            }
        }).start();

        new thread(new runnable() {
            @override
            public void run() {
                for(int i =0; i<100; i++) {
                    map<string, object> map = serialnumberprovider.generateserialnumber(param);
                    system.out.println("thread-2:" + map.get("result"));
                }
            }
        }).start();

        new thread(new runnable() {
            @override
            public void run() {
                for(int i =0; i<100; i++) {
                    map<string, object> map = serialnumberprovider.generateserialnumber(param);
                    system.out.println("thread-3:" + map.get("result"));
                }
            }
        }).start();

        byte[] b = new byte[0];
        synchronized(b) {
            b.wait();
        }

 

如果运行代码报以下错误

### 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、检查数据源连接用户是否有存储过程执行权限