文档章节

mongoldb主键生成策略

e
 evanchina
发布于 2016/06/30 16:56
字数 1877
阅读 25
收藏 0
点赞 0
评论 0

/** Copyright (c) 2008-2014 MongoDB, Inc.

 *

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *   http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

 

 

 

//import org.bson.diagnostics.Loggers;

 

import java.io.Serializable;

import java.net.NetworkInterface;

import java.nio.BufferUnderflowException;

import java.nio.ByteBuffer;

import java.security.SecureRandom;

import java.util.Date;

import java.util.Enumeration;

import java.util.concurrent.atomic.AtomicInteger;

//import java.util.logging.Level;

//import java.util.logging.Logger;

 

/**

 * <p>A globally unique identifier for objects.</p>

 *

 * <p>Consists of 12 bytes, divided as follows:</p>

 * <table border="1">

 *     <caption>ObjectID layout</caption>

 *     <tr>

 *         <td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td><td>11</td>

 *     </tr>

 *     <tr>

 *         <td colspan="4">time</td><td colspan="3">machine</td> <td colspan="2">pid</td><td colspan="3">inc</td>

 *     </tr>

 * </table>

 *

 * <p>Instances of this class are immutable.</p>

 *

 * @mongodb.driver.manual core/object-id ObjectId

 */

public final class ObjectId implements Comparable<ObjectId>, Serializable {

 

    private static final long serialVersionUID = 3670079982654483072L;

    private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(ObjectId.class);

    //static final Logger LOGGER = Loggers.getLogger("ObjectId");

     

 

    private static final int LOW_ORDER_THREE_BYTES = 0x00ffffff;

 

    private static final int MACHINE_IDENTIFIER;

    private static final short PROCESS_IDENTIFIER;

    private static final AtomicInteger NEXT_COUNTER = new AtomicInteger(new SecureRandom().nextInt());

 

    private final int timestamp;

    private final int machineIdentifier;

    private final short processIdentifier;

    private final int counter;

 

    /**

     * Gets a new object id.

     *

     * @return the new id

     */

    public static ObjectId get() {

        return new ObjectId();

    }

 

    /**

     * Checks if a string could be an {@code ObjectId}.

     *

     * @param hexString a potential ObjectId as a String.

     * @return whether the string could be an object id

     * @throws IllegalArgumentException if hexString is null

     */

    public static boolean isValid(final String hexString) {

        if (hexString == null) {

            throw new IllegalArgumentException();

        }

 

        int len = hexString.length();

        if (len != 24) {

            return false;

        }

 

        for (int i = 0; i < len; i++) {

            char c = hexString.charAt(i);

            if (c >= '0' && c <= '9') {

                continue;

            }

            if (c >= 'a' && c <= 'f') {

                continue;

            }

            if (c >= 'A' && c <= 'F') {

                continue;

            }

 

            return false;

        }

 

        return true;

    }

 

    /**

     * Gets the generated machine identifier.

     *

     * @return an int representing the machine identifier

     */

    public static int getGeneratedMachineIdentifier() {

        return MACHINE_IDENTIFIER;

    }

 

    /**

     * Gets the generated process identifier.

     *

     * @return the process id

     */

    public static int getGeneratedProcessIdentifier() {

        return PROCESS_IDENTIFIER;

    }

 

    /**

     * Gets the current value of the auto-incrementing counter.

     *

     * @return the current counter value.

     */

    public static int getCurrentCounter() {

        return NEXT_COUNTER.get();

    }

 

    /**

     * <p>Creates an ObjectId using time, machine and inc values.  The Java driver used to create all ObjectIds this way, but it does not

     * match the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>, which requires four values, not

     * three. This major release of the Java driver conforms to the specification, but still supports clients that are relying on the

     * behavior of the previous major release by providing this explicit factory method that takes three parameters instead of four.</p>

     *

     * <p>Ordinary users of the driver will not need this method.  It's only for those that have written there own BSON decoders.</p>

     *

     * <p>NOTE: This will not break any application that use ObjectIds.  The 12-byte representation will be round-trippable from old to new

     * driver releases.</p>

     *

     * @param time    time in seconds

     * @param machine machine ID

     * @param inc     incremental value

     * @return a new {@code ObjectId} created from the given values

     * @since 2.12.0

     */

    public static ObjectId createFromLegacyFormat(final int time, final int machine, final int inc) {

        return new ObjectId(time, machine, inc);

    }

 

    /**

     * Create a new object id.

     */

    public ObjectId() {

        this(new Date());

    }

 

    /**

     * Constructs a new instance using the given date.

     *

     * @param date the date

     */

    public ObjectId(final Date date) {

        this(dateToTimestampSeconds(date), MACHINE_IDENTIFIER, PROCESS_IDENTIFIER, NEXT_COUNTER.getAndIncrement(), false);

    }

 

    /**

     * Constructs a new instances using the given date and counter.

     *

     * @param date    the date

     * @param counter the counter

     * @throws IllegalArgumentException if the high order byte of counter is not zero

     */

    public ObjectId(final Date date, final int counter) {

        this(date, MACHINE_IDENTIFIER, PROCESS_IDENTIFIER, counter);

    }

 

    /**

     * Constructs a new instances using the given date, machine identifier, process identifier, and counter.

     *

     * @param date              the date

     * @param machineIdentifier the machine identifier

     * @param processIdentifier the process identifier

     * @param counter           the counter

     * @throws IllegalArgumentException if the high order byte of machineIdentifier or counter is not zero

     */

    public ObjectId(final Date date, final int machineIdentifier, final short processIdentifier, final int counter) {

        this(dateToTimestampSeconds(date), machineIdentifier, processIdentifier, counter);

    }

 

    /**

     * Creates an ObjectId using the given time, machine identifier, process identifier, and counter.

     *

     * @param timestamp         the time in seconds

     * @param machineIdentifier the machine identifier

     * @param processIdentifier the process identifier

     * @param counter           the counter

     * @throws IllegalArgumentException if the high order byte of machineIdentifier or counter is not zero

     */

    public ObjectId(final int timestamp, final int machineIdentifier, final short processIdentifier, final int counter) {

        this(timestamp, machineIdentifier, processIdentifier, counter, true);

    }

 

    private ObjectId(final int timestamp, final int machineIdentifier, final short processIdentifier, final int counter,

                     final boolean checkCounter) {

        if ((machineIdentifier & 0xff000000) != 0) {

            throw new IllegalArgumentException("The machine identifier must be between 0 and 16777215 (it must fit in three bytes).");

        }

        if (checkCounter && ((counter & 0xff000000) != 0)) {

            throw new IllegalArgumentException("The counter must be between 0 and 16777215 (it must fit in three bytes).");

        }

        this.timestamp = timestamp;

        this.machineIdentifier = machineIdentifier;

        this.processIdentifier = processIdentifier;

        this.counter = counter & LOW_ORDER_THREE_BYTES;

    }

 

    /**

     * Constructs a new instance from a 24-byte hexadecimal string representation.

     *

     * @param hexString the string to convert

     * @throws IllegalArgumentException if the string is not a valid hex string representation of an ObjectId

     */

    public ObjectId(final String hexString) {

        this(parseHexString(hexString));

    }

 

    /**

     * Constructs a new instance from the given byte array

     *

     * @param bytes the byte array

     * @throws IllegalArgumentException if array is null or not of length 12

     */

    public ObjectId(final byte[] bytes) {

        if (bytes == null) {

            throw new IllegalArgumentException();

        }

        if (bytes.length != 12) {

            throw new IllegalArgumentException("need 12 bytes");

        }

 

        timestamp = makeInt(bytes[0], bytes[1], bytes[2], bytes[3]);

        machineIdentifier = makeInt((byte) 0, bytes[4], bytes[5], bytes[6]);

        processIdentifier = (short) makeInt((byte) 0, (byte) 0, bytes[7], bytes[8]);

        counter = makeInt((byte) 0, bytes[9], bytes[10], bytes[11]);

    }

 

    /**

     * Creates an ObjectId

     *

     * @param timestamp                   time in seconds

     * @param machineAndProcessIdentifier machine and process identifier

     * @param counter                     incremental value

     */

    ObjectId(final int timestamp, final int machineAndProcessIdentifier, final int counter) {

        this(legacyToBytes(timestamp, machineAndProcessIdentifier, counter));

    }

 

    private static byte[] legacyToBytes(final int timestamp, final int machineAndProcessIdentifier, final int counter) {

        byte[] bytes = new byte[12];

        bytes[0] = int3(timestamp);

        bytes[1] = int2(timestamp);

        bytes[2] = int1(timestamp);

        bytes[3] = int0(timestamp);

        bytes[4] = int3(machineAndProcessIdentifier);

        bytes[5] = int2(machineAndProcessIdentifier);

        bytes[6] = int1(machineAndProcessIdentifier);

        bytes[7] = int0(machineAndProcessIdentifier);

        bytes[8] = int3(counter);

        bytes[9] = int2(counter);

        bytes[10] = int1(counter);

        bytes[11] = int0(counter);

        return bytes;

    }

 

    /**

     * Convert to a byte array.  Note that the numbers are stored in big-endian order.

     *

     * @return the byte array

     */

    public byte[] toByteArray() {

        byte[] bytes = new byte[12];

        bytes[0] = int3(timestamp);

        bytes[1] = int2(timestamp);

        bytes[2] = int1(timestamp);

        bytes[3] = int0(timestamp);

        bytes[4] = int2(machineIdentifier);

        bytes[5] = int1(machineIdentifier);

        bytes[6] = int0(machineIdentifier);

        bytes[7] = short1(processIdentifier);

        bytes[8] = short0(processIdentifier);

        bytes[9] = int2(counter);

        bytes[10] = int1(counter);

        bytes[11] = int0(counter);

        return bytes;

    }

 

    /**

     * Gets the timestamp (number of seconds since the Unix epoch).

     *

     * @return the timestamp

     */

    public int getTimestamp() {

        return timestamp;

    }

 

    /**

     * Gets the machine identifier.

     *

     * @return the machine identifier

     */

    public int getMachineIdentifier() {

        return machineIdentifier;

    }

 

    /**

     * Gets the process identifier.

     *

     * @return the process identifier

     */

    public short getProcessIdentifier() {

        return processIdentifier;

    }

 

    /**

     * Gets the counter.

     *

     * @return the counter

     */

    public int getCounter() {

        return counter;

    }

 

    /**

     * Gets the timestamp as a {@code Date} instance.

     *

     * @return the Date

     */

    public Date getDate() {

        return new Date(timestamp * 1000L);

    }

 

    /**

     * Converts this instance into a 24-byte hexadecimal string representation.

     *

     * @return a string representation of the ObjectId in hexadecimal format

     */

    public String toHexString() {

        StringBuilder buf = new StringBuilder(24);

 

        for (final byte b : toByteArray()) {

            buf.append(String.format("%02x", b & 0xff));

        }

 

        return buf.toString();

    }

 

    @Override

    public boolean equals(final Object o) {

        if (this == o) {

            return true;

        }

        if (o == null || getClass() != o.getClass()) {

            return false;

        }

 

        ObjectId objectId = (ObjectId) o;

 

        if (counter != objectId.counter) {

            return false;

        }

        if (machineIdentifier != objectId.machineIdentifier) {

            return false;

        }

        if (processIdentifier != objectId.processIdentifier) {

            return false;

        }

        if (timestamp != objectId.timestamp) {

            return false;

        }

 

        return true;

    }

 

    @Override

    public int hashCode() {

        int result = timestamp;

        result = 31 * result + machineIdentifier;

        result = 31 * result + (int) processIdentifier;

        result = 31 * result + counter;

        return result;

    }

 

    @Override

    public int compareTo(final ObjectId other) {

        if (other == null) {

            throw new NullPointerException();

        }

 

        int x = timestamp - other.timestamp;

        if (x != 0) {

            return x;

        }

 

        x = machineIdentifier - other.machineIdentifier;

        if (x != 0) {

            return x;

        }

 

        x = processIdentifier - other.processIdentifier;

        if (x != 0) {

            return x;

        }

 

        return counter - other.counter;

    }

 

    @Override

    public String toString() {

        return toHexString();

    }

 

    // Deprecated methods

 

    /**

     * Gets the time of this ID, in seconds.

     *

     * @deprecated Use #getTimestamp instead

     * @return the time component of this ID in seconds

     */

    @Deprecated

    public int getTimeSecond() {

        return timestamp;

    }

 

    /**

     * Gets the time of this instance, in milliseconds.

     *

     * @deprecated Use #getDate instead

     * @return the time component of this ID in milliseconds

     */

    @Deprecated

    public long getTime() {

        return timestamp * 1000L;

    }

 

    /**

     * @return a string representation of the ObjectId in hexadecimal format

     * @see ObjectId#toHexString()

     * @deprecated use {@link #toHexString()}

     */

    @Deprecated

    public String toStringMongod() {

        return toHexString();

    }

 

    static {

        try {

            MACHINE_IDENTIFIER = createMachineIdentifier();

            PROCESS_IDENTIFIER = createProcessIdentifier();

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

 

    private static int createMachineIdentifier() {

        // build a 2-byte machine piece based on NICs info

        int machinePiece;

        try {

            StringBuilder sb = new StringBuilder();

            Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();

            while (e.hasMoreElements()) {

                NetworkInterface ni = e.nextElement();

                sb.append(ni.toString());

                byte[] mac = ni.getHardwareAddress();

                if (mac != null) {

                    ByteBuffer bb = ByteBuffer.wrap(mac);

                    try {

                        sb.append(bb.getChar());

                        sb.append(bb.getChar());

                        sb.append(bb.getChar());

                    } catch (BufferUnderflowException shortHardwareAddressException) { //NOPMD

                        // mac with less than 6 bytes. continue

                    }

                }

            }

            machinePiece = sb.toString().hashCode();

        } catch (Throwable t) {

            // exception sometimes happens with IBM JVM, use random

            machinePiece = (new SecureRandom().nextInt());

            //LOGGER.log(Level.WARNING, "Failed to get machine identifier from network interface, using random number instead", t);

            LOGGER.warn("Failed to get machine identifier from network interface, using random number instead");

        }

        machinePiece = machinePiece & LOW_ORDER_THREE_BYTES;

        return machinePiece;

    }

 

    // Creates the process identifier.  This does not have to be unique per class loader because

    // NEXT_COUNTER will provide the uniqueness.

    private static short createProcessIdentifier() {

        short processId;

        try {

            String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();

            if (processName.contains("@")) {

                processId = (short) Integer.parseInt(processName.substring(0, processName.indexOf('@')));

            } else {

                processId = (short) java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();

            }

 

        } catch (Throwable t) {

            processId = (short) new SecureRandom().nextInt();

            //LOGGER.log(Level.WARNING, "Failed to get process identifier from JMX, using random number instead", t);

            LOGGER.warn("Failed to get process identifier from JMX, using random number instead");

        }

 

        return processId;

    }

 

    private static byte[] parseHexString(final String s) {

        if (!isValid(s)) {

            throw new IllegalArgumentException("invalid hexadecimal representation of an ObjectId: [" + s + "]");

        }

 

        byte[] b = new byte[12];

        for (int i = 0; i < b.length; i++) {

            b[i] = (byte) Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16);

        }

        return b;

    }

 

    private static int dateToTimestampSeconds(final Date time) {

        return (int) (time.getTime() / 1000);

    }

 

    // Big-Endian helpers, in this class because all other BSON numbers are little-endian

 

    private static int makeInt(final byte b3, final byte b2, final byte b1, final byte b0) {

        // CHECKSTYLE:OFF

        return (((b3) << 24) |

                ((b2 & 0xff) << 16) |

                ((b1 & 0xff) << 8) |

                ((b0 & 0xff)));

        // CHECKSTYLE:ON

    }

 

    private static byte int3(final int x) {

        return (byte) (x >> 24);

    }

 

    private static byte int2(final int x) {

        return (byte) (x >> 16);

    }

 

    private static byte int1(final int x) {

        return (byte) (x >> 8);

    }

 

    private static byte int0(final int x) {

        return (byte) (x);

    }

 

    private static byte short1(final short x) {

        return (byte) (x >> 8);

    }

 

    private static byte short0(final short x) {

        return (byte) (x);

    }

}

© 著作权归作者所有

共有 人打赏支持
e
粉丝 0
博文 2
码字总数 5402
作品 0
海淀
activiti uuid主键

1.1.1. activiti默认主键生成方式 分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) activiti中默认的主键生成的方式是:每次从activit...

分享达人
2016/05/04
0
0
常用Hibernate 主键生成策略

ORM映射基本原理 1. 基于相同实体类和表,实现相互映射,类的对象对应了表中的记录,不同对象对应不同的记录,不同的记录对应不同的对象 2. 表中不同的记录通过主键来区分,不同的对象通过对...

徐文瑞
2013/03/09
0
1
Hibernate4之JPA规范配置详解

@Table Table用来定义entity主表的name,catalog,schema等属性。 属性说明: name:表名 catalog:对应关系数据库中的catalog schema:对应关系数据库中的schema UniqueConstraints:定义一...

Zhao-Qian
2013/11/11
0
0
activiti5解决分布式集群部署的主键问题

一、概要综述 1、activiti5是jbpm4升级上来的一款最新版工作流引擎,已经将自己的表划分为4类:运行时、通用数据、历史数据、流程相关数据,但是 有一个核心问题就是是否支持集群部署,经过我...

提广乾
2013/06/07
0
0
JPA主键生成器和主键生成策略

JPA中创建实体时,需要声明实体的主键及其主键生成策略。我们有一个实体类叫做Email,其主键上声明如下: @Id@Column(name = "EMAIL_ID")@GeneratedValue(strategy = GenerationType.SEQUENC...

Element0506
2015/11/13
0
0
主键映射以及特殊类型映射(三)

前面没有过多的描述@Id标注,现在拿出来单独谈谈! 1、主键标识(@Id)属性定义如下: @Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface Id {} 2、标注@Id后,还要涉及@Gene...

半夏alvin
2012/11/25
0
0
activiti5.10解决分布式集群部署的主键问题

一、概要综述 1、activiti5是jbpm4升级上来的一款最新版工作流引擎,已经将自己的表划分为4类:运行时、通用数据、历史数据、流程相关数据,但是 有一个核心问题就是是否支持集群部署,经过我...

提广乾
2012/10/14
0
0
ZHYcms开源内容管理系统源码阅读

项目环境搭建 项目源码下载: https://github.com/shuogesha/ZHYcms 数据库mongoDB环境搭建: 软件下载: https://www.mongodb.org/downloads 软件安装教程: http://www.runoob.com/mongodb/m...

陈栋
2016/11/09
1K
0
基于按annotation的hibernate主键生成策略

这里讨论代理主键,业务主键(比如说复合键等)这里不讨论。 一、JPA通用策略生成器 通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 其生成规则由@Generate...

_白开水_
2013/10/02
0
0
Hibernate的ID生成策略

1.介绍 Hibernate是目前最为常用的ORM框架,当然也有人会选择iBATIS或者其他的架构.这里我们着重讲Hibernate的ID生成策略 2.可选的ID策略生成方式 (1)native/auto 根据不同的数据库采用不同的...

dmrs
2015/10/15
8
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

微信小程序Java登录流程(ssm实现具体功能和加解密隐私信息问题解决方案)

文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的微信公众号:好好学java,获取优质学习资源。 一、登录流程图 二、小程序客户端 doLogin:function(callback = () =>{}){let ...

公众号_好好学java
38分钟前
0
1
流利阅读笔记28-20180717待学习

“我不干了!” 英国脱欧大臣递交辞呈 雪梨 2018-07-17 1.今日导读 7 月 6 日,英国政府高官齐聚英国首相的官方乡间别墅——契克斯庄园,讨论起草了一份关于英国政府脱欧立场的白皮书。可是没...

aibinxiao
今天
7
0
OSChina 周二乱弹 —— 理解超算排名这个事,竟然超出了很多人的智商

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @-冰冰棒- :分享Ed Sheeran/Beyoncé的单曲《Perfect Duet (with Beyoncé)》 《Perfect Duet (with Beyoncé)》- Ed Sheeran/Beyoncé 手机...

小小编辑
今天
180
7
Android 获取各大音乐平台的真实下载地址

废话 电脑使用谷歌浏览器或者QQ浏览器的时候。。。。。。。说不清楚,还是看图吧 大概意思就是,只要网页上需要播放,只要能播放并且开始播放,这个过程就肯定会请求到相关的音乐资源,然后就...

她叫我小渝
今天
0
0
shell中的函数、shell中的数组、告警系统需求分析

shell中的函数 格式: 格式: function f_name() { command } 函数必须要放在最前面 示例1(用来打印参数) 示例2(用于定义加法) 示例3(用于显示IP) shell中的数组 shell中的数组1 定义数...

Zhouliang6
今天
2
0
用 Scikit-Learn 和 Pandas 学习线性回归

      对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了。 1. 获取数据,定义问题     没有...

wangxuwei
今天
1
0
MAC安装MAVEN

一:下载maven压缩包(Zip或tar可选),解压压缩包 二:打开终端输入:vim ~/.bash_profile(如果找不到该文件新建一个:touch ./bash_profile) 三:输入i 四:输入maven环境变量配置 MAVEN_HO...

WALK_MAN
今天
0
0
33.iptables备份与恢复 firewalld的9个zone以及操作 service的操作

10.19 iptables规则备份和恢复 10.20 firewalld的9个zone 10.21 firewalld关于zone的操作 10.22 firewalld关于service的操作 10.19 iptables规则备份和恢复: ~1. 保存和备份iptables规则 ~2...

王鑫linux
今天
2
0
大数据教程(2.11):keeperalived+nginx高可用集群搭建教程

上一章节博主为大家介绍了目前大型互联网项目的系统架构体系,相信大家应该注意到其中很重要的一块知识nginx技术,在本节博主将为大家分享nginx的相关技术以及配置过程。 一、nginx相关概念 ...

em_aaron
今天
1
1
Apache Directory Studio连接Weblogic内置LDAP

OBIEE默认使用Weblogic内置LDAP管理用户及组。 要整理已存在的用户及组,此前办法是导出安全数据,文本编辑器打开认证文件,使用正则表达式获取用户及组的信息。 后来想到直接用Apache Dire...

wffger
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部