Spring Data MongoDB: Обновление документа на основе нескольких идентификаторов с использованием Composite ID против MongoTemplate upsert против MongoRepository find & save - PullRequest
0 голосов
/ 26 марта 2020

Мне хотелось бы узнать, как лучше использовать документ на основе двух идентификаторов.

@Document(collection = "cars")
public class CarEntity {
    @Id
    private String id;
    private String color;
    private String brand;
    private Instant repairedAt;
        ...
}

Каждый автомобиль можно идентифицировать с помощью комбинации color и brand, которая является логическим идентификатором для сохранить документ. Я хочу обновить поле repairedAt.

Теперь есть (насколько мне известно) три хороших способа справиться с этим.

Вариант 1: Пользовательский репозиторий с пользовательским upsertOneByColorAndBrand который либо

1.a) использует CarRepository для внутреннего использования:

public void upsertOneByColorAndBrand(final CarEntity carNew,
                                           final String color,
                                           final String brand) {
    // findOneByColorAndBrand is no custom implementation, just from the interface
    var carExisting = repo.findOneByColorAndBrand(color, brand);
    if (carExisting == null) {
        // write to DB if not existent
        repo.save(carNew);
    } else {
        // update document if existing
        carExisting.setRepairedAt(carNew.getRepairedAt());
        repo.save(carExisting);
    }
}

1.b) или использует MongoTemplate внутренне:

public void upsertOneByColorAndBrand(final CarEntity carNew,
                                           final String color,
                                           final String brand) {
    // define find query
    Query query = new Query();
    query.addCriteria(Criteria.where("color").is(color));
    query.addCriteria(Criteria.where("brand").is(brand));

    // create document from entity
    Document doc = new Document();
    mongoTemplate.getConverter().write(carNew, doc);
    Update update = Update.fromDocument(doc);

    // upsert
    mongoTemplate.upsert(query, update, CarEntity.class);
}

Я сравнил производительность варианта 1.a и варианта 1.b, и разница в миллисекундах для трех документов git. Я думаю, это потому, что 1.a) разделяет операции «найти» и «сохранить».

Вариант 2: Вы также можете пропустить всю реализацию пользовательского репозитория и просто определить идентификатор сам документ, основанный на комбинации color & brand, поскольку в этом примере они уникальны. При этом вы можете просто использовать собственный repo.save(car), так как он будет автоматически использовать новый составной идентификатор для работы, который пропускает всю часть «поиска».

Существуют ли огромные недостатки / преимущества с опцией 2 ? По вашему опыту, является ли использование составного идентификатора в среде Spring Data хорошей идеей? Вы бы предпочли использовать составные индексы или «установить» идентификатор вручную при создании сущности?

...