Мне нужно написать приложение, с помощью которого я могу выполнять сложные запросы с использованием spring -data и mongodb. Я начал с использования MongoRepository, но боролся со сложными запросами, чтобы найти примеры или действительно понять синтаксис.
Я говорю о таких запросах:
@Repository
public interface UserRepositoryInterface extends MongoRepository<User, String> {
List<User> findByEmailOrLastName(String email, String lastName);
}
или использование запросов на основе JSON, которые я пробовал методом проб и ошибок, потому что не понимаю синтаксиса. Даже после прочтения документации mongodb (нерабочий пример из-за неправильного синтаксиса).
@Repository
public interface UserRepositoryInterface extends MongoRepository<User, String> {
@Query("'$or':[{'firstName':{'$regex':?0,'$options':'i'}},{'lastName':{'$regex':?0,'$options':'i'}}]")
List<User> findByEmailOrFirstnameOrLastnameLike(String searchText);
}
После прочтения всей документации кажется, что mongoTemplate
это гораздо лучше документировано MongoRepository
. Я имею в виду следующую документацию:
http://static.springsource.org/spring-data/data-mongodb/docs/current/reference/html/
Подскажите, что удобнее и мощнее в использовании? mongoTemplate
или MongoRepository
? Оба они одинаковы зрелые или у одного из них не хватает функций, чем у другого?
источник
YourRepository
, класс реализации должен быть названYourRepositoryImpl
. Так ли это? Если да, то я счастлив взглянуть на образец проекта на GitHub или подобном…CustomUserRepository
и нетCustomerUserRepository
.Этот ответ может быть немного запоздалым, но я бы рекомендовал избегать всего пути к репозиторию. Вы получаете очень мало реализованных методов, имеющих большую практическую ценность. Чтобы заставить его работать, вы сталкиваетесь с чушью конфигурации Java, на которую вы можете потратить дни и недели без особой помощи в документации.
Вместо этого, идите по
MongoTemplate
пути и создайте свой собственный уровень доступа к данным, который избавит вас от кошмаров конфигурации, с которыми сталкиваются программисты Spring.MongoTemplate
это действительно спаситель для инженеров, которым удобно создавать собственные классы и взаимодействия, поскольку существует большая гибкость. Структура может быть примерно такой:MongoClientFactory
класс, который будет работать на уровне приложения и предоставит вамMongoClient
объект. Вы можете реализовать это как Singleton или с помощью Enum Singleton (это потокобезопасный)источник
FWIW относительно обновлений в многопоточной среде:
MongoTemplate
обеспечивает «атомный» вне коробки операцийupdateFirst
,updateMulti
,findAndModify
,upsert
... , которые позволяют изменять документ в одной операции.Update
Объект , используемый эти методы также позволяет настроить таргетинг только соответствующие поля .MongoRepository
только дает вам основные операции CRUDfind
,insert
,save
,delete
, которые работают с POJOs , содержащей все поля . Это вынуждает вас либо обновить документы в несколько этапов (1.find
документ, который нужно обновить, 2. изменить соответствующие поля из возвращенного POJO, а затем 3.save
его), либо вручную определить свои собственные запросы на обновление@Query
.В многопоточной среде, такой как, например, серверная часть Java с несколькими конечными точками REST, обновление с использованием одного метода - это путь, чтобы уменьшить вероятность того, что два одновременных обновления перезапишут изменения друг друга.
Пример: учитывая такой документ:
{ _id: "ID1", field1: "a string", field2: 10.0 }
и два разных потока, одновременно обновляющих его ...С
MongoTemplate
ним будет выглядеть примерно так:THREAD_001 THREAD_002 | | |update(query("ID1"), Update().set("field1", "another string")) |update(query("ID1"), Update().inc("field2", 5)) | | | |
и окончательное состояние для документа всегда,
{ _id: "ID1", field1: "another string", field2: 15.0 }
поскольку каждый поток обращается к БД только один раз, и только указанное поле изменяется.В то время как тот же сценарий
MongoRepository
будет выглядеть так:THREAD_001 THREAD_002 | | |pojo = findById("ID1") |pojo = findById("ID1") |pojo.setField1("another string") /* field2 still 10.0 */ |pojo.setField2(pojo.getField2()+5) /* field1 still "a string" */ |save(pojo) |save(pojo) | | | |
и последний документ - это либо,
{ _id: "ID1", field1: "another string", field2: 10.0 }
либо в{ _id: "ID1", field1: "a string", field2: 15.0 }
зависимости от того, какаяsave
операция попадает в БД последней.(ПРИМЕЧАНИЕ: даже если бы мы использовали аннотацию Spring Data,
@Version
как предложено в комментариях, мало что изменилось бы: одна изsave
операций выдала быOptimisticLockingFailureException
, а окончательный документ все равно был бы одним из перечисленных выше, с обновлением только одного поля вместо обоих. )Поэтому я бы сказал, что
MongoTemplate
это лучший вариант , если у вас нет очень сложной модели POJO или вамMongoRepository
по какой-то причине не нужны возможности настраиваемых запросов .источник
@Version
можно «избежать» перезаписи вторым потоком данных, сохраненных первым - «избежать» в том смысле, что он отбросит обновление иOptimisticLockingFailureException
вместо этого выбросит . Так что вам придется реализовать механизм повтора, если вы хотите, чтобы обновление прошло успешно. MongoTemplate позволяет избежать всего сценария.