Мне хотелось бы узнать, как лучше использовать документ на основе двух идентификаторов.
@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 хорошей идеей? Вы бы предпочли использовать составные индексы или «установить» идентификатор вручную при создании сущности?