В чем разница между MongoTemplate Spring Data и MongoRepository?
мне нужно написать приложение, с помощью которого я могу выполнять сложные запросы, используя 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? Оба же зрелые или один из них не хватает больше возможностей, чем другие?
3 ответов:
"удобный" и "мощный в использовании" в какой-то степени противоречат целям. Репозитории намного удобнее, чем шаблоны, но последние, конечно, дают вам более мелкий контроль над тем, что выполнять.
поскольку модель программирования репозитория доступна для нескольких модулей данных Spring, вы найдете более подробную документацию по ней в общем разделе Spring Data MongoDB ссылка документы.
TL; DR
мы обычно рекомендуем следующий подход:
- начните с абстрактного репозитория и просто объявите простые запросы, используя механизм вывода запросов или вручную определенные запросы.
- для более сложных запросов добавьте в репозиторий методы, реализованные вручную (как описано здесь). Для реализации
MongoTemplate.подробности
для вашего примера это будет выглядеть так:
определите интерфейс для вашего пользовательского кода:
interface CustomUserRepository { List<User> yourCustomMethod(); }добавьте реализацию для этого класса и следуйте соглашению об именах, чтобы убедиться, что мы можем найти класс.
class UserRepositoryImpl implements CustomUserRepository { private final MongoOperations operations; @Autowired public UserRepositoryImpl(MongoOperations operations) { Assert.notNull(operations, "MongoOperations must not be null!"); this.operations = operations; } public List<User> yourCustomMethod() { // custom implementation here } }теперь пусть ваш базовый интерфейс репозитория расширит пользовательский и инфраструктуру будет автоматически использовать вашу пользовательскую реализацию:
interface UserRepository extends CrudRepository<User, Long>, CustomUserRepository { }таким образом, вы по существу получаете выбор: все, что просто легко объявить, входит в
UserRepository, все, что лучше реализовано вручную переходит вCustomUserRepository. Параметры настройки задокументированы здесь.
этот ответ может быть немного задержан, но я бы рекомендовал избегать всего маршрута репозитория. Вы получаете очень мало реализованных методов любой большой практической ценности. Чтобы заставить его работать, вы сталкиваетесь с ерундой конфигурации Java, на которую вы можете потратить дни и недели без особой помощи в документации.
СMongoTemplateмаршрут и создать свой собственный уровень доступа к данным, который освобождает вас от кошмаров конфигурации, с которыми сталкиваются весенние программисты.MongoTemplateЭто действительно спаситель для инженеров, которые комфортно проектируют свои собственные классы и взаимодействия, так как есть много гибкости. Структура может быть примерно такой:
- создать
MongoClientFactoryкласс, который будет работать на уровне приложения и дать вамMongoClient"объект". Вы можете реализовать это как синглтон или с помощью перечисления Синглтона (это потокобезопасно)- создать базовый класс доступа к данным, из которого можно наследовать объект доступа к данным для каждый объект домена). Базовый класс может реализовать метод для создания объекта MongoTemplate, который вы можете использовать для всех методов доступа к БД
- каждый класс доступа к данным для каждого объекта домена может реализовать основные методы или вы можете реализовать их в базовом классе
- методы контроллера могут затем вызывать методы в классах доступа к данным по мере необходимости.
FWIW, относительно обновлений в многопоточной среде:
MongoTemplateобеспечивает из коробкиupdateFirst,updateMulti,findAndModify,upsert... методы, которые позволяют изменять документ в одной операции. ЭлементUpdateобъект, используемый этими методами, также позволяет вам ориентироваться только на соответствующие поля.MongoRepositoryтолько дает вам основныеfind,insert,save,deleteоперации, с которыми работают POJOs, содержащий все поля. Это заставляет вас либо обновить документы в несколько шагов (findдокумент для обновления, измените соответствующие поля из возвращенного POJO, а затемsaveit), или определить свои собственные запросы обновления вручную с помощью@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операция сначала попадает в БД.так что я бы сказал, что
MongoTemplateлучший вариант, если у вас нет очень разработанной модели POJO или вам не нужны возможности пользовательских запросовMongoRepositoryпочему-то.
Comments