1. Background
When I use Hibernate to do object mapping, I always use the UUID to master the key. Since Hibernate's UUID needs to occupy 32-bit characters, it generally makes people feel more efficient and increase storage usage.
When I looked at the company project, I found a better way to build the UUID, which was to Base64 the UUID data. Feel more meaningful to come out to share with you.
2. Traditional Uuida, Java.util.UUID (RFC 4122 http://www.ietf.org/rfc/rfc4122.txt)
The UUID in Java uses the RFC 4122 standard, which is represented as 16 binary by standard data (36 characters). such as: F81d4fae-7dec-11d0-a765-00a0c91e6bf6
B, Hibernate UUID
Hibernate defaults to produce a UUID that, compared to the RFC 4122 standard, removes the unused "-" split symbol, so it is shorter (32 characters). such as: F81d4fae7dec11d0a76500a0c91e6bf6
3. UUID in BASE64 format
Since the characters used by the BASE64 encoding include 26 uppercase and lowercase letters, plus 10 digits, and a plus sign "+", a slash "/", altogether 64 characters. So the origin of the Base64 name. Base64 is equivalent to using 64 binary to represent the data, the same length number of bits in the case of more than the 16 binary representation of the content.
Since the UUID standard data is 128-bit in total, we can re-encode the 128-bit Base64.
The UUID of 128-bit is represented as two long data in Java, The Getleastsignificantbits and getmostsignificantbits in Java.util.UUID can be used to obtain two long (64-bit) respectively. Then we can get the uuid we want by Base64 transcoding.
Uuidutils Tool Class
?
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
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;
}
}
|
By calling the Uuidutils.compresseduuid () method, I can get the UUID string I need (22 characters, 128-bit Base64 only 22 characters). such as: Bwcyzlfgtactz9_juxsnya
10 characters shorter than Hibernate32 characters.
When dealing with Base64, the Apache COMMONS-CODEC Coding Toolkit is used here because it provides a simple encoding conversion method. There are also encodebase64urlsafestring methods that generate BASE64 encoding in a URL-safe manner. The default Base64 contains + and/characters, which will cause confusion if the encoding appears in the URL. The URL security method uses-replace +,_ replace/, and remove the end = =. Ideal for Web direct-pass parameters.
4. Hibernate's UUID generator
The implementation of the ID generator is slightly different (import) because Hibernate4 has made adjustments to the Sessionimplementor package.
A, Hibernate3?
123456789101112131415 |
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?
12345678910111213141516 |
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. Use the Base64 uuid in the mapping?
12345 |
@Id
@GenericGenerator
(name =
"uuidGenerator"
, strategy =
"org.noahx.uuid.Base64UuidGenerator"
)
@GeneratedValue
(generator =
"uuidGenerator"
)
@Column
(
"UUID"
, length =
22
)
private String uuid;
|
BASE64 compression UUID length replace hibernate legacy UUID Generator