实现类似mysql的主键递增功能, 并在此基础上做了增强, 可对于不同分类, 不同主键前缀自动递增。

表结构设计

t_sequence

字段

描述

ID

数据库主键

SEQ_PREFIX

生成的主键前缀

SEQ_TYPE

生成的主键类型

SEQ_NUM

生成的主键的最新序号

SEQ_GEN_DATE

主键最新更新时间

SEQ_CATEGORY

主键分类

SEQ_CHAR_WIDTH

主键数字部分的最大宽度, 如果seq_num的位数小于这个宽度, 则最终生成的主键前面补0

上代码:SequenceGenerator.java

public final class SequenceGenerator {

private static final Log logger = LogFactory.getLog(SequenceGenerator.class);

private static final String DEFAULT_SEQ_CATEGORY = "common";

private static final Integer DEFAULT_SEQ_CHAR_WIDTH=4;

private static final String SEQ_TYPE_NUMERIC="INT";

private static final String SEQ_TYPE_CHAR="VARCHAR2";

private final ReentrantLock lock = new ReentrantLock();

private static class SequenceGeneratorHolder{

private static SequenceGenerator instance = new SequenceGenerator();

}

private SequenceGenerator(){}

public static SequenceGenerator getInstance(){

return SequenceGeneratorHolder.instance;

}

public Integer getId(SequenceModel seqCriteria){

final ReentrantLock lock = this.lock;

lock.lock();

try{

SequenceService sequenceService = ApplicationContextProvider.getBean(SequenceService.class);

return sequenceService.getSeqId(seqCriteria); //查询数据库在最新的Seq_num基础上加1

}finally {

lock.unlock();

}

}

/**

* 默认生成不带前缀的字符串id

*

* @return

*/

public String generateStringId(){

return generateStringId(DEFAULT_SEQ_CATEGORY,DEFAULT_SEQ_CHAR_WIDTH);

}

/**

* 根据类别生成字符串ID, 使用默认字符宽度为4, 并且带前缀和category 一致

* @param category

* @return

*/

public String generateStringId(String category){

return generateStringId(category,category,DEFAULT_SEQ_CHAR_WIDTH);

}

public String generateStringId(String prefix,String category){

return generateStringId(prefix,category,DEFAULT_SEQ_CHAR_WIDTH);

}

/**

* generate varchar type id without prefix

* @param category

* @return

*/

public String generateStringId(String category, Integer charWidth){

return generateStringId(null,category,charWidth);

}

/**

*

* @param prefix

* @param category

* @param charWidth

* @return

*/

public String generateStringId(String prefix,String category, Integer charWidth){

SequenceModel seqCriteria = new SequenceModel();

seqCriteria.setSeqCategory(category);

seqCriteria.setSeqPrefix(prefix);

seqCriteria.setSeqCharWidth(charWidth);

seqCriteria.setSeqType(SEQ_TYPE_CHAR);

Integer result = getId(seqCriteria);

String numStr = StrUtil.padPre(String.valueOf(result),charWidth,'0');

String id = StrUtil.nullToEmpty(prefix)+numStr;

return id;

}

public Integer generateNumericId(){

return generateNumericId(DEFAULT_SEQ_CATEGORY);

}

/**

* generate long type id

* @return

*/

public Integer generateNumericId(String category){

SequenceModel seqCriteria = new SequenceModel();

seqCriteria.setSeqCategory(category);

seqCriteria.setSeqType(SEQ_TYPE_NUMERIC);

Integer result = getId(seqCriteria);

return result;

}

}

SequenceModel.java  ---表结构对象封装

@Data

public class SequenceModel {

private Integer id;

private String seqPrefix;

private String seqType;

private Integer seqNum;

private String seqCategory;

private Integer seqCharWidth;

private Date seqGenDate;

}

SequenceService.java

这里才是整个生成策略的核心, 查询数据库的时候需要加悲观锁, 锁住整行数据, 查询,插入, 更新需要在同一个事务内完成, 否则容易发生死锁。

使用Mybatis操作数据库

@Service

public class SequenceService {

@Autowired

private SequenceMapper sequenceMapper;

@Transactional(transactionManager = "businessDataSourceTM") // 这行不能少

public Integer getSeqId(SequenceModel seqCriteria){

try {

SequenceModel seqResult = sequenceMapper.findSequence(seqCriteria);

AtomicInteger atomicInteger = new AtomicInteger();

if(seqResult == null){

// 新建

seqResult = seqCriteria;

seqResult.setSeqNum(atomicInteger.incrementAndGet());

seqResult.setSeqGenDate(DateUtil.nowDate());

sequenceMapper.insertSequenceNum(seqResult);

}else{

//更新

Integer seqNum = seqResult.getSeqNum();

atomicInteger.set(seqNum);

seqResult.setSeqNum(atomicInteger.incrementAndGet());

seqResult.setSeqGenDate(DateUtil.nowDate());

sequenceMapper.updateSequenceNum(seqResult);

}

return atomicInteger.get();

} catch (Exception e) {

log.error("generate Id occurs error.",e);

return 0;

}

}

}

sequence-generator.xml -- mybatis SQL配置文件

select

seq.ID,

seq.SEQ_PREFIX,

seq.SEQ_TYPE,

seq.SEQ_NUM,

seq.SEQ_CHAR_WIDTH,

seq.SEQ_GEN_DATE,

seq.SEQ_CATEGORY

from t_sequence seq

where 1=1

and seq.SEQ_CATEGORY = #{seqCriteria.seqCategory}

and seq.SEQ_PREFIX = #{seqCriteria.seqPrefix}

for update

update t_sequence set seq_num=#{seq.seqNum}, seq_gen_date=#{seq.seqGenDate,jdbcType=TIMESTAMP} where id=#{seq.id}

SELECT CZBANK_COMMON_SEQ.NEXTVAL as ID from DUAL

insert into t_sequence (

id,

SEQ_PREFIX,

SEQ_TYPE,

SEQ_NUM,

SEQ_CHAR_WIDTH,

SEQ_GEN_DATE,

SEQ_CATEGORY

) VALUES (

#{id},

#{seq.seqPrefix,jdbcType=VARCHAR},

#{seq.seqType,jdbcType=VARCHAR},

#{seq.seqNum},

#{seq.seqCharWidth,jdbcType=INTEGER},

#{seq.seqGenDate},

#{seq.seqCategory}

)

SequenceMapper.java

@Mapper

public interface SequenceMapper {

SequenceModel findSequence(@Param("seqCriteria") SequenceModel seqCriteria);

void updateSequenceNum(@Param("seq") SequenceModel seq);

void insertSequenceNum(@Param("seq") SequenceModel seq);

}

java 数据路id增长策略_基于数据库实现ID自动生成策略相关推荐

  1. 用java写ods系统_基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(TableGo v7.0.0版)...

    TableGo是基于数据库的代码自动生成工具,低代码编程技术的实现,可以零代码自动生成SpringBoot项目工程.生成JavaBean.生成前后端分离的CRUD代码.生成MyBaits的Mapper ...

  2. java生成iso9660工具_基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(TableGo v7.0.0版)...

    TableGo_20210212 v7.0.0 正式版发布,此次版本更新如下: 1.新增对DB2数据库的支持 2.新增按字段生成文件,支持把字段.JSON.XML数据转换成任何代码 3.新增大量新的自 ...

  3. mysql javabean 工具_基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(v6.9.0版)...

    TableGo_20200520 v6.9.0 正式版发布,此次版本更新如下: 1.新增对JDK9及以上版本Java环境的支持 2.生成JavaBean更名为生成数据模型并且提供了C#.C++.Gol ...

  4. freemarker mysql 生成bean_基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(v6.6.6版)...

    TableGo_20191026 v6.6.6 正式发布,此次版本更新如下: 1.新增通过自定义模板生成Word文档的功能,可以使用FreeMarker模板生成自定义格式的数据库文档. 2.新增 Sw ...

  5. 基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(v6.9.0版)

    TableGo_20200520 v6.9.0 正式版发布,此次版本更新如下:           1.新增对JDK9及以上版本Java环境的支持           2.生成JavaBean更名为生 ...

  6. 基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(TableGo v7.4.0版)

    TableGo_20210921 v7.4.0 正式版发布,此次版本累计更新如下:           1.新增企业或个人的简单定制版本,为企业和个人提供软实力的增值           2.新增导入 ...

  7. mysql 分库分表策略_【数据库】分库分表策略

    关系型数据库本身比较容易成为系统瓶颈,单机存储容量.连接数.处理能力都有限.当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库.优化索引,做很多操作时性能仍下降严重.此时就要考 ...

  8. python股票策略_基于python的股票自动盯盘程序

    不是每个人都有时间时刻盯盘的,而且股票那么多,往往挂一漏万,错过很多好的股票和买入机会.笔者尝试用python实现了一个可以自动盯盘的程序,调用了一个免费的股票数据接口baostock提供的历史行情数 ...

  9. 用java做小学数学系统_小学生数学练习题目自动生成系统——java课程设计

    <小学生数学练习题目自动生成系统--java课程设计>由会员分享,可在线阅读,更多相关<小学生数学练习题目自动生成系统--java课程设计(37页珍藏版)>请在金锄头文库上搜索 ...

最新文章

  1. jsp与java_JSP与JavaBeans
  2. XCode真机测试发布时产生The executable was signed with invalid entitlements.解决办法
  3. MBE:ggtreeExtra-用图层叠加方法绘制环形进化树
  4. 真正理解线程上下文类加载器(多案例分析)
  5. Vertica 高可用性测试
  6. 多层mvc,thikphp进阶
  7. 数据库连接类:DatabaseConnection
  8. 智能城市dqn算法交通信号灯调度_博客 | 滴滴 KDD 2018 论文详解:基于强化学习技术的智能派单模型...
  9. 爬虫 动态生成useragent的功能 fake-useragent库
  10. maven报错:Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:x.x.x:test
  11. 大数据发展历程及技术选型
  12. Vue三大核心概念之二(事件)
  13. 屏蔽键盘信息(低级键盘钩子)
  14. 外星人 Alienware X14 评测
  15. Mac 安装IE浏览器
  16. Conflicted Confucians
  17. Linux perf 1.4、hardware events
  18. 曾经觉得学习晦涩难懂的我是如何爱上linux
  19. 集成显卡 独立显卡 CPU核心显卡的区别
  20. Windows Server域控制器更改IP步骤

热门文章

  1. 面向项目(二)—— visual studio 的使用
  2. Tricks(三十八)—— 在不计算欧式距离的前提下判断点到两点的距离哪个更近
  3. C基础——fopen() 的 mode参数
  4. 一行代码进行闰年的判断
  5. python列表删除行_Python DataFrame – 删除具有属于值列表的列值的行
  6. vue树形权限菜单_Vue.js 递归组件实现树形菜单
  7. python编程入门-Python 异步编程入门
  8. 0基础学python要多久-零基础python培训需要学多久?
  9. python教程-Python入门教程完整版(懂中文就能学会)
  10. 自学python好找工作么-学习python后好找工作吗