복붙노트

[MONGODB] MongoDB를 BSON 코덱 부호화 대상 동안 사용되지

MONGODB

MongoDB를 BSON 코덱 부호화 대상 동안 사용되지

오류 메시지와 함께 객체를 인코딩 할 때 나는 MongoDB를 데이터베이스 (MongoDB를 3.0.2 사용)에서 개체를 저장하려고 해요와 CodecConfigurationException 무엇입니까

Can't find a codec for class java.time.LocalDate. 

나는 작성하고 LOCALDATE 개체에 대한 코덱을 포함했다. 세부 사항은 다음과 같습니다.

개체, DutyBlock, 나는 가게를 시도하고있어한다는 것은 이러한 멤버 변수가 있습니다 :

public class DutyBlock {
    private LocalDate startDate;
    private LocalDate endDate; //Inclusive
    private int blockLength;
    private double pointValue;
    private ArrayList<Ra> assigned;
}

나는 데이터베이스 내의 DutyBlock 개체를 인코딩하기 위해 다음과 같은 코덱을 썼다 :

public class DutyBlockCodec implements Codec<DutyBlock> {

    @Override
    public void encode(BsonWriter writer, DutyBlock t, EncoderContext ec) {
        Document document = new Document();
        document.append("startDate", t.getStartDate());
        document.append("endDate", t.getEndDate());
        document.append("blockLength", t.getBlockLength());
        document.append("pointValue", t.getPointValue());
        document.append("assigned", t.getRasOnDuty());

        writer.writeString(document.toJson());  //Line 27 in the error message.
    }

    @Override
    public Class<DutyBlock> getEncoderClass() {
        return DutyBlock.class;
    }

    @Override
    public DutyBlock decode(BsonReader reader, DecoderContext dc) {
        String json = reader.readString();
        return new DutyBlock(Document.parse(json));
    }

}

MongoDB를 현재 java.time.LocalDate 클래스를 지원하지 않기 때문에, 나는 LOCALDATE가 데이터베이스에서 개체를 인코딩하기 위해 다음 코덱을 서면으로 작성했습니다 :

public class LocalDateCodec implements Codec<LocalDate> {

    @Override
    public void encode(BsonWriter writer, LocalDate t, EncoderContext ec) {
        writer.writeString(t.toString());
    }

    @Override
    public Class<LocalDate> getEncoderClass() {
        return LocalDate.class;
    }

    @Override
    public LocalDate decode(BsonReader reader, DecoderContext dc) {
        String date = reader.readString();
        return LocalDate.parse(date);
    }
}

내가 추가 한 두 개의 코덱 년대 MongoClient 수준에서 CodecRegistry에 MongoClient를 인스턴스화하는 동안 (Ra의 유형에 대한 하나와 함께).

public class DutyScheduleDB {
    private MongoClient mongoClient;
    private MongoDatabase db;

    public DutyScheduleDB() {
        CodecRegistry codecRegistry = 
                CodecRegistries.fromRegistries(
                        CodecRegistries.fromCodecs(new LocalDateCodec(), new DutyBlockCodec(), new RaCodec()),
                        MongoClient.getDefaultCodecRegistry());
        MongoClientOptions options = MongoClientOptions.builder()
                .codecRegistry(codecRegistry).build();
        mongoClient = new MongoClient(new ServerAddress(), options);
        db = mongoClient.getDatabase("DutySchedulerDB");
    }
    . (More code not shown)
    .
    .
}

나는 MongoDB를 데이터베이스 내에서 org.bson.Document의 일환으로 DutyBlock 개체의 ArrayList를 저장하려고.

public void storeScheduledCalendar(String id,
        String calendarName,
        ArrayList<DutyBlock> cal) {
    //Access collection of scheduled calendars.
    MongoCollection collection = db.getCollection("ScheduledCalendars");
    //Query parameter is uuid + calendarName.
    Document doc = new Document("name", id + calendarName);
    doc.append("dutyBlocks", cal);
    //Insert doc to collection.
    collection.insertOne(doc); //Line 59 in the error message.
}

그러나, 나는이 오류 메시지가 실행 해요 :

Exception in thread "main" org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.time.LocalDate.
at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:174)
at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:189)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:131)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
at org.bson.Document.toJson(Document.java:294)
at org.bson.Document.toJson(Document.java:268)
at org.bson.Document.toJson(Document.java:255)
at SchedulingHeuristic.DutyBlockCodec.encode(DutyBlockCodec.java:27)
at SchedulingHeuristic.DutyBlockCodec.encode(DutyBlockCodec.java:16)
at org.bson.codecs.EncoderContext.encodeWithChildContext(EncoderContext.java:91)
at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:175)
at org.bson.codecs.DocumentCodec.writeIterable(DocumentCodec.java:197)
at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:170)
at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:189)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:131)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at com.mongodb.connection.InsertCommandMessage.writeTheWrites(InsertCommandMessage.java:99)
at com.mongodb.connection.InsertCommandMessage.writeTheWrites(InsertCommandMessage.java:43)
at com.mongodb.connection.BaseWriteCommandMessage.encodeMessageBody(BaseWriteCommandMessage.java:112)
at com.mongodb.connection.BaseWriteCommandMessage.encodeMessageBody(BaseWriteCommandMessage.java:35)
at com.mongodb.connection.RequestMessage.encode(RequestMessage.java:132)
at com.mongodb.connection.BaseWriteCommandMessage.encode(BaseWriteCommandMessage.java:89)
at com.mongodb.connection.WriteCommandProtocol.sendMessage(WriteCommandProtocol.java:170)
at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:73)
at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:66)
at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:37)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:155)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:219)
at com.mongodb.connection.DefaultServerConnection.insertCommand(DefaultServerConnection.java:108)
at com.mongodb.operation.MixedBulkWriteOperation$Run$2.executeWriteCommandProtocol(MixedBulkWriteOperation.java:416)
at com.mongodb.operation.MixedBulkWriteOperation$Run$RunExecutor.execute(MixedBulkWriteOperation.java:604)
at com.mongodb.operation.MixedBulkWriteOperation$Run.execute(MixedBulkWriteOperation.java:363)
at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:148)
at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:141)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:186)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:177)
at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:141)
at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:72)
at com.mongodb.Mongo.execute(Mongo.java:747)
at com.mongodb.Mongo$2.execute(Mongo.java:730)
at com.mongodb.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:482)
at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:277)
at DutyScheduleDB.storeScheduledCalendar(DutyScheduleDB.java:59)
at DutyScheduleDB.main(DutyScheduleDB.java:106)

인코딩 DutyBlock 객체에 시도 할 때 내가 확인한하지만 LOCALDATE 내 코덱이 사용되지 않는 것으로 보인다 내가 참으로 통해 LocalDateCodec 포함되어 있습니까에 org.bson.Document을 저장하려고 오전 컬렉션

System.out.println(collection.getCodecRegistry().get(LocalDate.class));

사람이 왜 이런 일이 몇 가지 통찰력을 제공 할 수 있습니까?

해결법

  1. ==============================

    1.연구의 몇 일 후, 나는 해결책을 알아 냈어요.

    연구의 몇 일 후, 나는 해결책을 알아 냈어요.

    DutyBlockCodec 인코딩 / 디코딩하기 위해 (I 만든 있음) LocalDateCodec에 의존한다. 이 종속성은 그냥 같은 코덱 레지스트리에 두 개의 코덱을 추가하여 만족하지 않습니다. 용액 DutyBlockCodec에 의존하는 코덱을 포함하는 CodecRegistry 객체를 전달하는 (예를 들어 LocalDateCodec 그 안에 함유 CodecRegistry) 멤버 변수로서 저장되는 DutyBlockCodec의 생성자이다. 인코딩에 LocalDateCodec를 사용하기 위해서는, I 인코딩에 코덱, 작가, 소자에 전달하는 EncoderContext.encodeWithChildContext () 메소드를 사용한다. 또한, 나는 개별 필드보다는 (내 원래의 코드에서와 같이) 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이 필요합니다. 나는 LocalDateCodec와 CodecRegistry을 만들 수 있습니다 생각하지만, 다음 다음이 오히려 혼란 모두 LocalDateCodec 및 DutyBlockCodec를 포함하는 다른 CodecRegistry을 생성, 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;
        }
    }
    

    나는 CodecRegistries.fromProviders () 메소드를 사용하여 MongoDB를 클라이언트에이 CodecProviders을 추가했다.

    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에서 찾을 수 있습니다 나는 사람들이 가질 수있는 질문에 대답 열려입니다.

  2. from https://stackoverflow.com/questions/30569228/mongodb-bson-codec-not-being-used-while-encoding-object by cc-by-sa and MIT license