Base64压缩UUID长度替换Hibernate原有UUID生成器

1、背景

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

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

2、传统UUID

a、java.util.UUID(RFC 4122 http://www.ietf.org/rfc/rfc4122.txt

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工具类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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();
     }
 
}

5、映射中使用Base64的UUID

?
1
2
3
4
5
@Id
     @GenericGenerator (name = "uuidGenerator" , strategy = "org.noahx.uuid.Base64UuidGenerator" )
     @GeneratedValue (generator = "uuidGenerator" )
     @Column ( "UUID" , length = 22 )
     private String uuid;

6、总结

有时读代码就像看书,总是可以带来惊喜。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值