首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分布式下规则生成主键

分布式下规则生成主键

作者头像
小小明童鞋
发布2018-06-13 16:18:05
1.1K0
发布2018-06-13 16:18:05
举报
文章被收录于专栏:java系列博客java系列博客

首先,建一张用于存储自增序列的表,相当于所有的按此规则生成主键的表在此都会有对应一条记录。

建表语句:

CREATE TABLE PUB_SEQUENCE_NUMBER(
  prefix VARCHAR(10) NOT NULL PRIMARY KEY COMMENT '前缀(主键)',
  NAME  VARCHAR(30) NOT NULL COMMENT '描述',
  today char(8) NOT NULL COMMENT '当天日期',
  minNum INTEGER NOT NULL DEFAULT 0 COMMENT '序列号最小号码',
  currentNum INTEGER NOT NULL DEFAULT 0 COMMENT '当前序列号',
  numLength INTEGER NOT NULL DEFAULT 8 COMMENT '序列号长度'
);

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.suning.primarykey</groupId>
    <artifactId>tigbs-primarykey</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.3</version>
        </dependency>

        <!-- test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <scope>test</scope>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.12</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.7</version>
        </dependency>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <!-- aop -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.8</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.8.8</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.8</version>
        </dependency>
        <!--spring mybatis 整合-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.13</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.13</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <scope>runtime</scope>
            <version>1.7.13</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <nonFilteredFileExtensions>
                        <nonFilteredFileExtension>tbl</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

对应实体类:

package com.cn.tigbs.bean;

/**
 * 报表主键生成策略bean
 */
public class SequenceNumber {
    //序列前缀
    private String prefix;
    //
    private String name;
    //当前日期转换为字符串形式
    private String today;

    private int minNum;
    private int currentNum;
    private int numLength;

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getToday() {
        return today;
    }

    public void setToday(String today) {
        this.today = today;
    }

    public int getMinNum() {
        return minNum;
    }

    public void setMinNum(int minNum) {
        this.minNum = minNum;
    }

    public int getCurrentNum() {
        return currentNum;
    }

    public void setCurrentNum(int currentNum) {
        this.currentNum = currentNum;
    }

    public int getNumLength() {
        return numLength;
    }

    public void setNumLength(int numLength) {
        this.numLength = numLength;
    }

    public SequenceNumber() {
    }

    public SequenceNumber(String prefix, String name, int minNum, int currentNum, int numLength) {
        this.prefix = prefix;

        this.name = name;
        this.minNum = minNum;
        this.currentNum = currentNum;
        this.numLength = numLength;
    }

    @Override
    public String toString() {
        return "SequenceNumber{" +
                "prefix='" + prefix + '\'' +
                ", name='" + name + '\'' +
                ", today='" + today + '\'' +
                ", minNum=" + minNum +
                ", currentNum=" + currentNum +
                ", numLength=" + numLength +
                '}';
    }
}

对应dao层:

import com.cn.tigbs.bean.SequenceNumber;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface SequenceNumberDao {

    /**
     * 根据前缀生成一个序列号信息
     * @param prefix 前缀
     * @return
     */
    SequenceNumber newSequenceNumber(@Param("prefix") String prefix);

    /**
     * 将生成的序列号更新到数据库
     * @param sequnceNumber 需要更新信息
     */
    void updateSequenceNumber(@Param("bean") SequenceNumber sequnceNumber);

    /**
     * 获取数据库当天日期
     * @return
     */
    String getToday();
}

用于存储要生成对应主键的表的枚举类:

package com.cn.tigbs.Enum;

import com.cn.tigbs.bean.SequenceNumber;

public enum SequenceNumberEnum {
    SEA(new SequenceNumber("SEA","海洋",1,1,8)),
    COD(new SequenceNumber("CLOUD","云",1,1,8))
    ;

    private SequenceNumber sequenceNumber;

    public SequenceNumber getSequenceNumber() {
        return sequenceNumber;
    }

    public void setSequenceNumber(SequenceNumber sequenceNumber) {
        this.sequenceNumber = sequenceNumber;
    }

    SequenceNumberEnum(SequenceNumber sequenceNumber) {
        this.sequenceNumber = sequenceNumber;
    }
}

service:

package com.cn.tigbs.service;

import com.cn.tigbs.Enum.SequenceNumberEnum;

public interface SequenceNumberService {
    /**
     * 生成一个主键
     * @param sequenceNumberEnum 主键生成类型
     * @return 返回一个生成的主键
     */
    String newSequenceNumberEnum(SequenceNumberEnum sequenceNumberEnum);
}

实现类:

package com.cn.tigbs.impl;

import com.cn.tigbs.Enum.SequenceNumberEnum;
import com.cn.tigbs.bean.SequenceNumber;
import com.cn.tigbs.dao.SequenceNumberDao;
import com.cn.tigbs.service.SequenceNumberService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class SequenceNumberServiceImpl implements SequenceNumberService {

    @Resource
    private SequenceNumberDao sequenceNumberDao;

    @Override
    public synchronized String newSequenceNumberEnum(SequenceNumberEnum sequenceNumberEnum) {
        if (sequenceNumberEnum == null) {
            return null;
        }
        SequenceNumber sequenceNumber = sequenceNumberDao.newSequenceNumber(sequenceNumberEnum.getSequenceNumber().getPrefix());

        if (sequenceNumber == null) {
            sequenceNumber = sequenceNumberEnum.getSequenceNumber();
            sequenceNumber.setToday(sequenceNumberDao.getToday());
        }

        sequenceNumberDao.updateSequenceNumber(sequenceNumber);
        return String.format("%s%6s%08d", sequenceNumber.getPrefix(), sequenceNumber.getToday(), sequenceNumber.getCurrentNum());
    }
}

mybatis 配置文件:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <properties>
        <property name="dialect" value="mysql"/>
        <property name="pageSqlId" value=".*Page$"/>
    </properties>
    <settings>
        <setting name="cacheEnabled" value="false"/>
        <setting name="lazyLoadingEnabled" value="false"/>
    </settings>
    <!--<plugins>-->
    <!--<plugin interceptor="com.cmbchina.common.interceptor.PageInterceptor"/>-->
    <!--</plugins>-->

</configuration>

spring 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="com.suning.tigbs" />


    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/demo?useUnicode=yes&amp;characterEncoding=utf8&amp;allowMultiQueries=true"/>
        <property name="username" value="root"/>
        <property name="password" value="xmtx"/>
        <property name="minIdle" value="10"/>
        <property name="maxIdle" value="10"/>
        <property name="maxWaitMillis" value="-1"/>
        <property name="maxTotal" value="10"/>
    </bean>
    <!-- spring和MyBatis整合-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation"
                  value="classpath:META-INF/mybatis/sql-map-config.xml" />
        <property name="mapperLocations" value="classpath*:META-INF/mybatis/mapper/*Dao.xml" />
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" id="mapperScannerConfigurer">
        <property name="annotationClass" value="org.springframework.stereotype.Repository"/>
        <property name="basePackage" value="com.suning.tigbs.dao"/>
    </bean>

    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="*"  propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* *..*ServiceImpl*.*(..))"/>
    </aop:config>
</beans>

测试类:

package com.cn.tigbs.impl;

import com.cn.tigbs.Enum.SequenceNumberEnum;
import com.cn.tigbs.service.SequenceNumberService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

import static org.junit.Assert.*;

public class SequenceNumberServiceImplTest {
    @Test
    public void newSequeceNumberEnum() throws Exception {

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/spring/spring-base-jdbc.xml");
        SequenceNumberService sequenceNumberService = applicationContext.getBean(SequenceNumberService.class);
        Queue<String> queue = new ArrayBlockingQueue<String>(2000);
        List<Thread> list = new ArrayList<>();
        for (int i = 0;i < 2000; i ++){
            list.add(new Thread(()->{
                String key = sequenceNumberService.newSequenceNumberEnum(SequenceNumberEnum.SEA);

                queue.add(key);
            }));
        }
        for (Thread thread : list){
            thread.start();
        }

        while (queue.size() != 2000);
        System.out.println(queue);
    }


    public static void main(String[] args) {



            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/spring/spring-base-jdbc.xml");
            SequenceNumberService sequenceNumberService = applicationContext.getBean(SequenceNumberService.class);
            Queue<String> queue = new ArrayBlockingQueue<String>(50);
            List<Thread> list = new ArrayList<>();
            for (int i = 0;i < 50; i ++){
                list.add(new Thread(()->{
                    String key = sequenceNumberService.newSequenceNumberEnum(SequenceNumberEnum.SEA);

                    queue.add(key);
                }));
            }
            for (Thread thread : list){
                thread.start();
            }

            while (queue.size() != 50);
            System.out.println(queue);
        }



}

码云地址:

https://gitee.com/xiaomingnevermind/primarykey

文件可能会是空的,有时间的时候上传github,和码云。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档