Sau nhiều ngày nghiên cứu, tôi đã tìm ra giải pháp.
DutyBlockCodec
phụ thuộc vào LocalDateCodec
(mà tôi đã tạo) để mã hóa / giải mã. Sự phụ thuộc này không được thỏa mãn chỉ bằng cách thêm hai codec vào cùng một sổ đăng ký codec. Giải pháp là chuyển một CodecRegistry
đối tượng chứa codec DutyBlockCodec
phụ thuộc vào (ví dụ:một CodecRegistry
chứa trong nó LocalDateCodec
) vào DutyBlockCodec
hàm tạo của, được lưu trữ dưới dạng một biến thành viên. Để sử dụng LocalDateCodec
để mã hóa, tôi sử dụng EncoderContext.encodeWithChildContext()
phương thức, truyền codec, trình viết và phần tử để mã hóa. Ngoài ra, tôi viết các trường riêng lẻ thay vì viết một Document
dưới dạng String
(như trong mã gốc của tôi). Do đó, DutyBlock
codec cuối cùng trông như thế này:
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
phụ thuộc vào codec khác và do đó yêu cầu CodecRegistry
được chuyển vào hàm tạo của nó. Mặc dù tôi tin rằng có thể tạo CodecRegistry
với LocalDateCodec
, sau đó chuyển điều này làm đối số cho DutyBlockCodec
hàm tạo của, sau đó tạo một CodecRegistry
khác chứa cả LocalDateCodec
và DutyBlockCodec
, điều này khá khó hiểu và MongoDB cung cấp một chức năng, CodecProvider
để tạo điều kiện thuận lợi cho quá trình này.
Sử dụng CodecProvider
giao diện, tôi đã viết một 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;
}
}
Tôi đã thêm những CodecProviders
này tới Ứng dụng khách MongoDB bằng CodecRegistries.fromProviders()
phương pháp.
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");
Mã nguồn của tôi cho dự án này có thể được tìm thấy tại https://github.com/desrepair/DutySchedulerTôi sẵn sàng trả lời bất kỳ câu hỏi nào mà mọi người có thể có.