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;
  • 相关阅读:
    HTML元素解释
    Java命名规范
    HDU 1058 Humble Numbers(DP,数)
    HDU 2845 Beans(DP,最大不连续和)
    HDU 2830 Matrix Swapping II (DP,最大全1矩阵)
    HDU 2870 Largest Submatrix(DP)
    HDU 1421 搬寝室(DP)
    HDU 2844 Coins (组合背包)
    HDU 2577 How to Type(模拟)
    HDU 2159 FATE(二维完全背包)
  • 原文地址:https://www.cnblogs.com/suncj/p/4230457.html
Copyright © 2011-2022 走看看