“Convenient” and “powerful to use” are contradicting goals to some degree. Repositories are by far more convenient than templates but the latter of course give you more fine-grained control over what to execute.
As the repository programming model is available for multiple Spring Data modules, you’ll find more in-depth documentation for it in the general section of the Spring Data MongoDB reference docs.
TL;DR
We generally recommend the following approach:
- Start with the repository abstract and just declare simple queries using the query derivation mechanism or manually defined queries.
- For more complex queries, add manually implemented methods to the repository (as documented here). For the implementation use
MongoTemplate
.
Details
For your example this would look something like this:
-
Define an interface for your custom code:
interface CustomUserRepository { List<User> yourCustomMethod(); }
-
Add an implementation for this class and follow the naming convention to make sure we can find the class.
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 } }
-
Now let your base repository interface extend the custom one and the infrastructure will automatically use your custom implementation:
interface UserRepository extends CrudRepository<User, Long>, CustomUserRepository { }
This way you essentially get the choice: everything that just easy to declare goes into UserRepository
, everything that’s better implemented manually goes into CustomUserRepository
. The customization options are documented here.