使用MongoClient读取Spring Data写入MongoDB的UUID转换问题
解决方案
问题根源
- Spring Data MongoDB默认使用Legacy Java UUID编码存储UUID类型字段,和标准RFC4122的UUID字节序不同,存储时会对高低位字节做大小端反转
java.util.UUID#nameUUIDFromBytes是基于输入字节做MD5哈希生成类型3 UUID的方法,不是用来解码已有UUID二进制内容的,所以转换结果和原始值不一致
转换方法
方法1:使用MongoDB驱动自带工具类(推荐)
直接调用驱动内置的UUIDHelper即可处理遗留编码转换:
import org.bson.types.Binary; import org.bson.types.UUIDHelper; // 读取文档中的_id字段 Binary idBinary = doc.get("_id", Binary.class); // 第二个参数传true表示使用Java遗留编码规则解码 UUID originalUuid = UUIDHelper.toUuid(idBinary.getData(), true);
方法2:手动实现字节序转换
如果不想依赖驱动内部工具类,可以自己实现字节序调整逻辑:
public static UUID legacyJavaBytesToUuid(byte[] bytes) { if (bytes == null || bytes.length != 16) { throw new IllegalArgumentException("UUID字节数组长度必须为16"); } // 构造最高有效位 long mostSigBits = (long) (bytes[3] & 0xff) << 56 | (long) (bytes[2] & 0xff) << 48 | (long) (bytes[1] & 0xff) << 40 | (long) (bytes[0] & 0xff) << 32 | (long) (bytes[5] & 0xff) << 24 | (bytes[4] & 0xff) << 16 | (bytes[7] & 0xff) << 8 | (bytes[6] & 0xff); // 构造最低有效位 long leastSigBits = (long) (bytes[15] & 0xff) << 56 | (long) (bytes[14] & 0xff) << 48 | (long) (bytes[13] & 0xff) << 40 | (long) (bytes[12] & 0xff) << 32 | (long) (bytes[11] & 0xff) << 24 | (bytes[10] & 0xff) << 16 | (bytes[9] & 0xff) << 8 | (bytes[8] & 0xff); return new UUID(mostSigBits, leastSigBits); }
调用方式:
Binary idBinary = doc.get("_id", Binary.class); UUID originalUuid = legacyJavaBytesToUuid(idBinary.getData());
内容的提问来源于stack exchange,提问作者jjrz
相关产品推荐
相关产品推荐

