【发布时间】:2019-08-21 13:26:18
【问题描述】:
我正在使用 MongoDB 及其反应流 Java 驱动程序(在 Spring 引导项目中)为现有的数据库访问模块。一些对象以复合方式存储在 DB 中,仅存储参考 ID,然后在从 DB 获取时组装对象(参见示例代码)。我正在使用编解码器来创建 Java 对象,但我不确定如何以复合方式制作东西。
以前使用同步驱动程序的解决方案只是逐字段解析从 MongoDB 返回的文档,并在需要进行数据库查找以进行组装时调用适当的服务。由于该解决方案很快变得完全无法管理,因此我决定使用 MongoDB 编解码器将文档直接解析为 Java 对象。但是,我不确定如何使用编解码器做同样的事情,因为它们似乎不允许我连接到数据库以在创建对象时获取适当的数据,并且在创建后对这些对象进行额外的获取和手动设置似乎效率低下而不是真正正确的方法。
MongoDB 规则集合示例:
{
"_id": {
"$oid": "5afa865b613640f83206e23e"
},
"id": "R2",
"typeId": "RT1",
"name": "example rule",
}
RuleType 集合示例:
{
"_id": {
"$oid": "5afa865c613640f83206e260"
},
"id": "RT1",
"name": "Example rule type",
}
Rule.java
public Class Rule {
private id;
private name;
private RuleType ruleType;
// Constructors, setters, getters, etc.
}
RuleType.java
public Class Rule {
private id;
private name;
// Constructors, setters, getters, etc.
}
RuleDbService.java
public class RuleDbService {
private final MongoCollection<Rule> ruleCollection;
private final ObservableSubscriber<Rule> subscriber = new ObservableSubscriber<>();
public RuleDbService(final MongoDbAdapter mongoDbAdapter) {
this.ruleCollection = mongoDbAdapter.getCollection("rules", Rule.class);
}
public Optional<Rule> findFirst() {
this.ruleCollection.find().first().subscribe(this.subscriber);
return Optional.of(this.subscriber.get())
}
RulesCodec.java
public class RulesCodec implements Codec<Rule> {
private final Codec<Document> documentCodec;
public RulesCodec() {
this.documentCodec = new DocumentCodec();
}
public RulesCodec(final Codec<Document> codec) {
this.documentCodec = codec;
}
@Override
public Rule decode(final BsonReader reader, final DecoderContext decoderContext) {
final Document document = this.documentCodec.decode(reader, decoderContext);
final Rule rule = new Rule();
rule.setId(document.getString("id"));
// rule.setType() <- How to do this? Can I call to some findById(id) function in RuleTypeDbService from here?
rule.setName(document.getString("name"));
return rule;
}
@Override
public void encode(final BsonWriter writer, final Rule value, final EncoderContext encoderContext) {
final Document document = new Document();
final String ruleId = value.getId();
final String name = value.getName();
final String typeId = (value.getType() != null) ? value.getType().getId() : null;
if (ruleId != null) {
document.put("id", ruleId);
}
if (name != null) {
document.put("name", name);
}
if (typeId != null) {
document.put("typeId", typeId);
}
this.documentCodec.encode(writer, document, encoderContext);
}
@Override
public Class<Rule> getEncoderClass() {
return Rule.class;
}
}
我希望 RuleDbService 能够通过在数据库中查找来组装包括 ruleType 的规则,而不是用空字段返回它,并且我必须在编解码器解析后手动进行外部查找和类型设置或其他一些解决方法。最好的方法是什么?
注意:很遗憾,我无法以任何方式修改数据库或模型结构,因此我无法使用任何 ORM 框架(如 Morphia)需要 MongoDb 中的唯一 id 字段在 Java 模型中表示,因此我必须对文档进行解码手动。
【问题讨论】:
标签: java mongodb codec reactive-streams