zoukankan      html  css  js  c++  java
  • Base64压缩UUID长度替换Hibernate原有UUID生成器

    本文来自http://my.oschina.net/noahxiao/blog/132277,个人储藏使用

    1、背景

    在采用Hibernate做对象映射时,我一直都采用UUID来做主键。由于Hibernate的UUID需要占用32位的字符,所以一般都会让人感觉响效率且增加存储占用。

    我在查看公司项目时发现了一种比较好的生成UUID的方法,就是将UUID数据进行Base64化。觉得比较有意义拿出来给大家分享。

    2、传统UUID

    a、java.util.UUID

    Java中的UUID采用RFC 4122的标准,按标准数据按16进制进行表示(36个字符)。如:f81d4fae-7dec-11d0-a765-00a0c91e6bf6

    b、Hibernate UUID

    Hibernate默认产生的UUID与RFC 4122标准相比,去掉了没有用的"-"分割符号,所以更短(32个字符)。如:f81d4fae7dec11d0a76500a0c91e6bf6

    3、Base64格式的UUID

    由于Base64编码使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符。所以才有Base64名字的由来。Base64相当于使用64进制来表示数据,相同长度位数的情况下要比16进制表示更多的内容。

    由于UUID标准数据总共是128-bit,所以我们就可以对这个128-bit重新进行Base64编码。

    128-bit的UUID在Java中表示为两个long型数据,可以采用java.util.UUID中的getLeastSignificantBits与getMostSignificantBits分别获得两个long(64-bit)。再通过Base64转码就可以获得我们所要的UUID。

    UuidUtils工具类

    package org.noahx.uuid;
     
    import org.apache.commons.codec.binary.Base64;
     
    import java.util.UUID;
     
    public abstract class UuidUtils {
     
        public static String uuid() {
            UUID uuid = UUID.randomUUID();
            return uuid.toString();
        }
     
        public static String compressedUuid() {
            UUID uuid = UUID.randomUUID();
            return compressedUUID(uuid);
        }
     
        protected static String compressedUUID(UUID uuid) {
            byte[] byUuid = new byte[16];
            long least = uuid.getLeastSignificantBits();
            long most = uuid.getMostSignificantBits();
            long2bytes(most, byUuid, 0);
            long2bytes(least, byUuid, 8);
            String compressUUID = Base64.encodeBase64URLSafeString(byUuid);
            return compressUUID;
        }
     
        protected static void long2bytes(long value, byte[] bytes, int offset) {
            for (int i = 7; i > -1; i--) {
                bytes[offset++] = (byte) ((value >> 8 * i) & 0xFF);
            }
        }
     
        public static String compress(String uuidString) {
            UUID uuid = UUID.fromString(uuidString);
            return compressedUUID(uuid);
        }
     
        public static String uncompress(String compressedUuid) {
            if (compressedUuid.length() != 22) {
                throw new IllegalArgumentException("Invalid uuid!");
            }
            byte[] byUuid = Base64.decodeBase64(compressedUuid + "==");
            long most = bytes2long(byUuid, 0);
            long least = bytes2long(byUuid, 8);
            UUID uuid = new UUID(most, least);
            return uuid.toString();
        }
     
        protected static long bytes2long(byte[] bytes, int offset) {
            long value = 0;
            for (int i = 7; i > -1; i--) {
                value |= (((long) bytes[offset++]) & 0xFF) << 8 * i;
            }
            return value;
        }
    }

    通过调用UuidUtils.compressedUuid()方法就可以获得我的需要的UUID字符串(22个字符,128-bit的Base64只需要22个字符)。如:BwcyZLfGTACTz9_JUxSnyA

    比Hibernate32个字符还短了10个字符。

    在处理Base64时,这里用到了apache的commons-codec编码工具包,因为它提供了简单的编码转换方法。而且还有encodeBase64URLSafeString方法,采用URL安全方式生成Base64编码。默认的Base64含有+与/字符,如果这种编码出现在URL中将造成混乱。URL安全方式采用了-替换+,_替换/,并去掉了结束==。非常适合Web直接传参。

    4、Hibernate的UUID生成器

    由于Hibernate4对SessionImplementor的包做出了调整所以ID生成器的实现稍有不同(import)。

    a、Hibernate3

    package org.noahx.uuid;
     
    import org.hibernate.HibernateException;
    import org.hibernate.engine.SessionImplementor;
    import org.hibernate.id.IdentifierGenerator;
     
    import java.io.Serializable;
     
    public class Base64UuidGenerator implements IdentifierGenerator {
     
        @Override
        public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
            return UuidUtils.compressedUuid();
        }
    }

    b、Hibernate4

    package org.noahx.uuid;
     
    import org.hibernate.HibernateException;
    import org.hibernate.engine.spi.SessionImplementor;
    import org.hibernate.id.IdentifierGenerator;
     
    import java.io.Serializable;
     
    public class Base64UuidGenerator implements IdentifierGenerator {
     
        @Override
        public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
            return UuidUtils.compressedUuid();
        }
     
    }

    映射中使用Base64的UUID

    @Id
        @GenericGenerator(name = "uuidGenerator", strategy = "org.noahx.uuid.Base64UuidGenerator")
        @GeneratedValue(generator = "uuidGenerator")
        @Column("UUID", length = 22)
        private String uuid;
  • 相关阅读:
    Ubuntu 16 安装redis客户端
    crontab 参数详解
    PHP模拟登录发送闪存
    Nginx配置端口访问的网站
    Linux 增加对外开放的端口
    Linux 实用指令之查看端口开启情况
    无敌的极路由
    不同的域名可以指向同一个项目
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error
    Redis 创建多个端口
  • 原文地址:https://www.cnblogs.com/suncj/p/4230457.html
Copyright © 2011-2022 走看看