使用 MongoClient 读取写入 Spring 数据的 UUID

Using MongoClient to read UUID written to with Spring Data

我无法读取使用 Spring 数据 MongoDB 写入 MongoDB 集合的 UUID 值。对于 UUID ca119807-967a-46df-b659-f0e5e4163a28,数据库中的值为 _id : Binary('30Z6lgeYEcooOhbk5fBZtg==', 3).

这就是我使用 Spring 数据 MongoDB 将 UUID 写入数据库的方式:

@Document("foos")
class Foo {

@Id
private UUID uuid;
...

在使用 com.mongodb.client.MongoClient 获取相同文档后,我能够访问 org.bson.types.Binary 类型的字段。然后看起来像这样:

这就是我实例化上面列出的变量的方式:

Binary id = doc.get("_id", Binary.class);
String base64String = Base64.encodeBase64String(id.getData());

我无法将此值转换回原始 UUID。将 byte[] 传递给 java.util.UUID#nameUUIDFromBytes 会产生与原始 UUID 完全不同的结果。

如何将org.bson.types.Binary中的byte[]转换为UUID?

我设法使用 Studio 3T 读取 UUID 值。为此,我不得不将 Legacy UUID Encoding 更改为“Legacy Java Encoding”。在我这样做之前,我看到的 UUID 值与我从 java.util.UUID#nameUUIDFromBytes.

获得的值相同

BSON 二进制子类型 3 是旧的 UUID 格式。未定义遗留字节顺序,因此每种客户端语言都可以自由地以对该语言的实现有意义的任何方式对字节进行排序。

十六进制的base64数据30Z6lgeYEcooOhbk5fBZtg==是:

df46 7a96 0798 11ca 283a 16e4 e5f0 59b6

如果将其与原始 UUID ca119807-967a-46df-b659-f0e5e4163a28 进行比较,您可能会注意到十六进制的前半部分:

df46 7a96 0798 11ca

是UUID前半部分的倒序:

ca119807-967a-46df

下半场同样如此:

283a 16e4 e5f0 59b6
b659-f0e5e4163a28

MongoDB Java 驱动程序的 org.bson.UuidRepresentation 枚举给出了问题的线索,它有可能的值:

C_SHARP_LEGACY
JAVA_LEGACY
PYTHON_LEGACY
STANDARD

上面的特殊编码是JAVA_LEGACY格式。

有关如何指定使用哪个,请参阅 spring-boot 2.3.6, how to set UUID representation for mongo?

感谢@Joe 的回答,我能够使用 org.mongodb:bson:423 中的实用程序来解码 JAVA_LEGACY 字节:

import org.bson.Document;
import org.bson.UuidRepresentation;
import org.bson.conversions.Bson;
import org.bson.internal.UuidHelper;
import org.bson.types.Binary;

(...)

result.map(document -> {
Binary id = document.get("_id", Binary.class);
byte[] data = id.getData();
byte type = id.getType();
return UuidHelper.decodeBinaryToUuid(data, type, 
        UuidRepresentation.JAVA_LEGACY);
}) (...)

结果与 Spring 数据 MongoDB.

的 UUID 值相同