-
Notifications
You must be signed in to change notification settings - Fork 0
Repositories
Repositories are the next layer above the Models. They are an abstraction whose goal is to significantly reduce the amount of boilerplate code required to implement data access to our entities. This is one of the features that Spring automates the best, as you'll see in the following chapters.
[Spring Docs] about repositories is very good, so this section of the Wiki will be shorter and mostly limited to the features used in the project.
To establish a repository that is readily usable, you can effortlessly define an interface that extends the Repository
interface and is marked with the @Repository
annotation. To accurately formulate this interface, you will need to specify the two generics: one for the entity and the other for the ID type (usually Long
). Spring will then take care of all the necessary setup for the query system (yes, this feature is a bit magical).
Nevertheless, there are different types of repositories and it's crucial to comprehend the main distinctions prior to their utilization:
-
Repository
: Principally operates as a marker interface, aiding in the identification of interfaces that extend it. It is rarely used unless customizations are being implemented, as it lacks useful methods. -
CrudRepository
: Offers CRUD operations for the specified entity, including reading, creation, updating, and deletion. This interface is the most commonly used. -
PagingAndSortingRepository
: Extends Repository and provides extra methods to handle pagination and sorting mechanisms. It's often combined with CrudRepository to include CRUD methods. -
ListCrudRepository
/ListPagingAndSortingRepository
: Equal to their non-list counterparts, but return aList
instead of anIterable
whenever applicable. -
CoroutineCrudRepository
/CoroutineSortingRepository
: Equal to their non-coroutine counterparts, but using Kotlin Coroutines. -
JpaRepository
: An extension of ListCrudRepository, JpaRepository is a specializedJPA
implementation of repositories. It essentially inherits the features of ListCrudRepository while incorporating additional functionalities, like methods for flushing pending alterations to the database. It is advisable to utilize the more generalized interfaces unless specific requirements necessitate the use of JpaRepository.
If you ever need to create your own abstraction for repositories, you can create an interface with the @NoRepositoryBean
to prevent Spring from initializing it.
To actually create the repository, you need just two lines of code:
@Repository
interface RoleRepository : CrudRepository<Role, Long>
Sources: Spring Docs and StackOverflow
The default repositories come with handy methods, but they might not cover all the queries we need. In Spring, we can easily define most queries by just creating a method in an interface following a specific pattern. Spring takes care of parsing the method name and generating the correct query! You can find the potential queries and their formats in the documentation, but here are a few examples.
Additionally, you can craft custom queries in a SQL-like language called JPQL using the @Query annotation. There's even an optional parameter nativeQuery
to construct raw SQL queries.
@Repository
interface GenerationRepository : CrudRepository<Generation, Long> {
// Returns null if not found
fun findBySchoolYear(schoolYear: String): Generation?
// Orders generations and retrieves the first one
fun findFirstByOrderBySchoolYearDesc(): Generation?
@Query("SELECT schoolYear FROM Generation ORDER BY schoolYear DESC")
fun findAllSchoolYearOrdered(): List<String>
}
@Repository
interface AccountRepository : PagingAndSortingRepository<Account, Long>, CrudRepository<Account, Long> {
// Search for both name and email
fun findByNameAndEmail(name: String, email: String): List<Account>
// Search for either name or email
fun findDistinctByNameOrEmail(name: String, email: String): List<Account>
// Case insensitive query
fun findByNameIgnoreCase(name: String): List<Account>
// Using pagination
fun findByName(name: String, pageable: Pageable): Page<Account>
}
Source: Spring Docs
Getting Started
Architecture Details
Implementation Details
Testing
Documentation
Deployment