数日間の調査の結果、解決策を見つけました。
DutyBlockCodec
LocalDateCodec
に依存します (私が作成した)エンコード/デコードするため。この依存関係は、2つのコーデックを同じコーデックレジストリに追加するだけでは満たされません。解決策は、CodecRegistry
を渡すことです。 DutyBlockCodec
であるコーデックを含むオブジェクト に依存します(例:CodecRegistry
その中にLocalDateCodec
が含まれています )DutyBlockCodec
に のコンストラクタ。メンバー変数として格納されます。 LocalDateCodec
を使用するには エンコードするには、EncoderContext.encodeWithChildContext()
を使用します メソッド、エンコードするコーデック、ライター、および要素を渡します。さらに、Document
を書くのではなく、個々のフィールドを書きます String
として (私の元のコードのように)。したがって、DutyBlock
コーデックは次のようになります:
public class DutyBlockCodec implements Codec<DutyBlock> {
private final CodecRegistry codecRegistry;
public DutyBlockCodec(final CodecRegistry codecRegistry) {
this.codecRegistry = codecRegistry;
}
@Override
public void encode(BsonWriter writer, DutyBlock t, EncoderContext ec) {
writer.writeStartDocument();
Codec dateCodec = codecRegistry.get(LocalDate.class);
writer.writeName("startDate");
ec.encodeWithChildContext(dateCodec, writer, t.getStartDate());
writer.writeName("endDate");
ec.encodeWithChildContext(dateCodec, writer, t.getEndDate());
writer.writeName("blockLength");
writer.writeInt32(t.getBlockLength());
writer.writeName("pointValue");
writer.writeDouble(t.getPointValue());
//Writing ArrayList of RAs
writer.writeName("assigned");
writer.writeStartArray();
for (Ra ra : t.getRasOnDuty()) {
Codec raCodec = codecRegistry.get(Ra.class);
ec.encodeWithChildContext(raCodec, writer, ra);
}
writer.writeEndArray();
writer.writeEndDocument();
}
@Override
public Class<DutyBlock> getEncoderClass() {
return DutyBlock.class;
}
@Override
public DutyBlock decode(BsonReader reader, DecoderContext dc) {
reader.readStartDocument();
Codec<LocalDate> dateCodec = codecRegistry.get(LocalDate.class);
reader.readName();
LocalDate startDate = dateCodec.decode(reader, dc);
reader.readName();
LocalDate endDate = dateCodec.decode(reader, dc);
reader.readName();
int blockLength = reader.readInt32();
reader.readName();
double pointValue = reader.readDouble();
//Reading ArrayList of RAs
reader.readName();
Codec<Ra> raCodec = codecRegistry.get(Ra.class);
ArrayList<Ra> rasOnDuty = new ArrayList<>();
reader.readStartArray();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
rasOnDuty.add(raCodec.decode(reader, dc));
}
reader.readEndArray();
reader.readEndDocument();
return new DutyBlock(startDate, endDate, blockLength, pointValue, rasOnDuty);
}
}
DutyBlockCodec
別のコーデックに依存しているため、CodecRegistry
が必要です コンストラクターに渡されます。 CodecRegistry
を作成することは可能だと思いますが LocalDateCodec
を使用 、次にこれを引数としてDutyBlockCodec
に渡します のコンストラクター、次に別のCodecRegistry
を作成します 両方のLocalDateCodec
を含む およびDutyBlockCodec
、これはかなり紛らわしいです、そしてMongoDBは機能、CodecProvider
を提供します このプロセスを容易にするため。
CodecProvider
の使用 インターフェイス、DutyBlockCodecProvider
を作成しました
public class DutyBlockCodecProvider implements CodecProvider {
@Override
public <T> Codec<T> get(Class<T> type, CodecRegistry cr) {
if (type == DutyBlock.class) {
return (Codec<T>) new DutyBlockCodec(cr);
}
return null;
}
}
これらのCodecProviders
を追加しました CodecRegistries.fromProviders()
を使用してMongoDBクライアントに メソッド。
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(new LocalDateCodec()),
CodecRegistries.fromProviders(
new RaCodecProvider(),
new DutyBlockCodecProvider(),
new ScheduledDutyCodecProvider()),
MongoClient.getDefaultCodecRegistry());
MongoClientOptions options = MongoClientOptions.builder()
.codecRegistry(codecRegistry).build();
mongoClient = new MongoClient(new ServerAddress(), options);
db = mongoClient.getDatabase("DutySchedulerDB");
このプロジェクトの私のソースコードはhttps://github.com/desrepair/DutySchedulerにあります。人々からの質問に答えることができます。