MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Bộ giải mã MongoDB BSON không được sử dụng khi mã hóa đối tượng

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ả LocalDateCodecDutyBlockCodec , đ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ó.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Xây dựng các API REST bằng EVE

  2. tạo và cập nhật nhiều tài liệu MongoDB trong một lần gọi

  3. MongoDB thêm vào trường bộ sưu tập tham gia từ cơ sở một

  4. Dữ liệu mùa xuân Khớp và Lọc Mảng lồng nhau

  5. Có mã hóa dự phòng cho MySQL, MongoDB &PostgreSQL - ClusterControl 1.5.1