В чем разница между 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? Оба же зрелые или один из них не хватает больше возможностей, чем другие?

819   3  

3 ответов:

"удобный" и "мощный в использовании" в какой-то степени противоречат целям. Репозитории намного удобнее, чем шаблоны, но последние, конечно, дают вам более мелкий контроль над тем, что выполнять.

поскольку модель программирования репозитория доступна для нескольких модулей данных Spring, вы найдете более подробную документацию по ней в общем разделе Spring Data MongoDB ссылка документы.

TL; DR

мы обычно рекомендуем следующий подход:

  1. начните с абстрактного репозитория и просто объявите простые запросы, используя механизм вывода запросов или вручную определенные запросы.
  2. для более сложных запросов добавьте в репозиторий методы, реализованные вручную (как описано здесь). Для реализации MongoTemplate.

подробности

для вашего примера это будет выглядеть так:

  1. определите интерфейс для вашего пользовательского кода:

    interface CustomUserRepository {
    
      List<User> yourCustomMethod();
    }
    
  2. добавьте реализацию для этого класса и следуйте соглашению об именах, чтобы убедиться, что мы можем найти класс.

    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
      }
    }
    
  3. теперь пусть ваш базовый интерфейс репозитория расширит пользовательский и инфраструктуру будет автоматически использовать вашу пользовательскую реализацию:

    interface UserRepository extends CrudRepository<User, Long>, CustomUserRepository {
    
    }
    

таким образом, вы по существу получаете выбор: все, что просто легко объявить, входит в UserRepository, все, что лучше реализовано вручную переходит в CustomUserRepository. Параметры настройки задокументированы здесь.

этот ответ может быть немного задержан, но я бы рекомендовал избегать всего маршрута репозитория. Вы получаете очень мало реализованных методов любой большой практической ценности. Чтобы заставить его работать, вы сталкиваетесь с ерундой конфигурации Java, на которую вы можете потратить дни и недели без особой помощи в документации.

С MongoTemplate маршрут и создать свой собственный уровень доступа к данным, который освобождает вас от кошмаров конфигурации, с которыми сталкиваются весенние программисты. MongoTemplate Это действительно спаситель для инженеров, которые комфортно проектируют свои собственные классы и взаимодействия, так как есть много гибкости. Структура может быть примерно такой:
  1. создать MongoClientFactory класс, который будет работать на уровне приложения и дать вам MongoClient "объект". Вы можете реализовать это как синглтон или с помощью перечисления Синглтона (это потокобезопасно)
  2. создать базовый класс доступа к данным, из которого можно наследовать объект доступа к данным для каждый объект домена). Базовый класс может реализовать метод для создания объекта MongoTemplate, который вы можете использовать для всех методов доступа к БД
  3. каждый класс доступа к данным для каждого объекта домена может реализовать основные методы или вы можете реализовать их в базовом классе
  4. методы контроллера могут затем вызывать методы в классах доступа к данным по мере необходимости.

FWIW, относительно обновлений в многопоточной среде:

  • MongoTemplate обеспечивает из коробки updateFirst,updateMulti,findAndModify,upsert... методы, которые позволяют изменять документ в одной операции. Элемент Update объект, используемый этими методами, также позволяет вам ориентироваться только на соответствующие поля.
  • MongoRepository только дает вам основные find,insert,save,delete операции, с которыми работают POJOs, содержащий все поля. Это заставляет вас либо обновить документы в несколько шагов (find документ для обновления, измените соответствующие поля из возвращенного POJO, а затем save it), или определить свои собственные запросы обновления вручную с помощью @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

    Ничего не найдено.