MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Codec MongoDB BSON tidak digunakan saat menyandikan objek

Setelah beberapa hari melakukan penelitian, saya menemukan solusinya.

DutyBlockCodec tergantung pada LocalDateCodec (yang saya buat) untuk menyandikan/mendekode. Ketergantungan ini tidak terpenuhi hanya dengan menambahkan dua codec ke dalam registri codec yang sama. Solusinya adalah dengan memberikan CodecRegistry objek yang berisi codec yang DutyBlockCodec tergantung pada (mis. CodecRegistry berisi LocalDateCodec di dalamnya ) ke DutyBlockCodec 's konstruktor, yang disimpan sebagai variabel anggota. Untuk menggunakan LocalDateCodec untuk encode, saya menggunakan EncoderContext.encodeWithChildContext() metode, meneruskan codec, penulis, dan elemen untuk dikodekan. Selain itu, saya menulis bidang individual daripada menulis Document sebagai String (seperti dalam kode asli saya). Jadi DutyBlock codec akhirnya terlihat seperti ini:

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 bergantung pada codec lain, sehingga memerlukan CodecRegistry untuk diteruskan ke konstruktornya. Meskipun saya yakin itu mungkin untuk membuat CodecRegistry dengan LocalDateCodec , lalu berikan ini sebagai argumen ke DutyBlockCodec konstruktor , lalu buat CodecRegistry lainnya berisi LocalDateCodec dan DutyBlockCodec , ini agak membingungkan, dan MongoDB menyediakan fungsionalitas, CodecProvider untuk memfasilitasi proses ini.

Menggunakan CodecProvider antarmuka, saya menulis 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;
    }
}

Saya menambahkan CodecProviders ini ke Klien MongoDB menggunakan CodecRegistries.fromProviders() metode.

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");

Kode sumber saya untuk proyek ini dapat ditemukan di https://github.com/desrepair/DutySchedulerSaya terbuka untuk menjawab pertanyaan apa pun yang mungkin dimiliki orang.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Referensi dokumen luwak dengan hubungan satu-ke-banyak

  2. Buat Indeks Wildcard di MongoDB

  3. Bagaimana cara terhubung ke cluster Atlas M0 (Free Tier) dengan benar melalui driver Java?

  4. Cassandra vs. MongoDB

  5. Bagaimana cara menghitung total lari menggunakan agregat?