Spring, MongoDB и upserts: работает с отдельными обновлениями, не работает с массовыми обновлениями.

В моем тестовом коде я сначала выполняю обычный upsert, используя MongoTemplate.upsert(). Он правильно добавляет данные в БД, и в БД появляется следующий документ, как и ожидалось:

{ "_id" : 1, "elements" : [ { "payload" : "payload" } ] }

Затем я выполняю аналогичный upsert, используя BulkOperations. Это не удается со следующим исключением:

org.bson.codecs.configuration.CodecConfigurationException: не удается найти кодек для элемента класса.

Я думал, что эти два вызова должны выполняться одинаково. Я что-то упустил в BulkOperations API? Как я могу выполнять массовые операции для кодирования объектов так же, как это делают обычные операции?

Использую mongo-java-driver 3.3.0 (аналогичную проблему можно наблюдать и на 2.14.3)

public class Main {
    public static void main(String[] args) throws UnknownHostException {
        MongoTemplate template = new MongoTemplate(new Mongo("localhost"), "local");

        // works
        template.upsert(makeQuery(1), makeUpdate(), Data.class);

        // fails miserably
        BulkOperations ops = template.bulkOps(BulkOperations.BulkMode.UNORDERED, Data.class);
        ops.upsert(makeQuery(2), makeUpdate());
        ops.execute();
    }

    private static Query makeQuery(int id) {
        return Query.query(Criteria.where("id").is(id));
    }

    private static Update makeUpdate() {
        Update update = new Update();
        update.set("elements", Collections.singletonList(new Element()));
        return update;
    }
}

@Document(collection = "test")
class Data {
    private int id = 1;
    private List<Element> elements;
}

class Element {
    private String payload = "payload";
}

person infthi    schedule 10.10.2016    source источник


Ответы (1)


Похоже, что в spring-data-mongo есть ошибка, когда массово обновляется поле List, а элемент в List не является скаляром (например, String, Integer). Он жалуется, что нет codes.

Есть один способ избежать этого

private static Update makeUpdate() {
    Update update = new Update();
    update.set("elements", mongoConverter.convertToMongoType(Collections.singletonList(new Element())));
    return update;
}

где mongoConverter - это org.springframework.data.mongodb.core.convert.mongoConverter, и вы можете автоматически связать экземпляр в своем компоненте.

person a.l.    schedule 26.04.2017