diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/Repository.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/Repository.java index cdb2ad294..46c0c4aee 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/Repository.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/Repository.java @@ -3,7 +3,16 @@ package org.springframework.data.repository; import java.io.Serializable; /** - * + * Central repository marker interface. Captures the domain type to manage as well as the domain type's id type. General + * purpose is to hold type information as well as being able to discover interfaces that extend this one during + * classpath scanning for easy Spring bean creation. + *

+ * Domain repositories extending this interface can selectively expose CRUD methods by simply declaring methods of the + * same signature as those declared in {@link CrudRepository}. + * + * @see CrudRepository + * @param the domain type the repository manages + * @param the type of the id of the entity the repository manages * @author Oliver Gierke */ public interface Repository { diff --git a/src/docbkx/repositories.xml b/src/docbkx/repositories.xml index d2117bde1..865dcc296 100644 --- a/src/docbkx/repositories.xml +++ b/src/docbkx/repositories.xml @@ -29,8 +29,11 @@ The central interface in Spring Data repository abstraction is Repository (probably not that much of a surprise). It is typeable to the domain class to manage as well as the id - type of the domain class and provides some sophisticated functionality - around CRUD for the entity managed. + type of the domain class. This interface mainly acts as marker interface + to capture the types to deal with and helps us discovering interface that + extend this one. Beyond that there's + CrudRepository which provides some + sophisticated functionality around CRUD for the entity managed. Repository interface @@ -43,8 +46,6 @@ - - @@ -52,15 +53,13 @@ - public interface Repository<T, ID extends Serializable> { + public interface CrudRepository<T, ID extends Serializable> { T save(T entity); - T findById(ID primaryKey); + T findOne(ID primaryKey); - List<T> findAll(); - - Page<T> findAll(Pageable pageable); + Iterable<T> findAll(); Long count(); @@ -84,10 +83,6 @@ Returns all entities. - - Returns a page of entities. - - Returns the number of entities. @@ -108,23 +103,23 @@ implementations for a variety of Spring Data modules that implement that interface. - On top of the Repository there is a PagingAndSortingRepository - abstraction that adds additional methods to ease paginated access to - entities: + On top of the CrudRepository there is + a PagingAndSortingRepository abstraction + that adds additional methods to ease paginated access to entities: PagingAndSortingRepository public interface PagingAndSortingRepository<T, ID extends Serializable> extends Repository<T, ID> { - List<T> findAll(Sort sort); + Iterable<T> findAll(Sort sort); Page<T> findAll(Pageable pageable); } - Accessing the second page of User by a page size of 20 you could - simply do something like this: + Accessing the second page of User by a page + size of 20 you could simply do something like this: PagingAndSortingRepository<User, Long> repository = // … get access to a bean Page<User> users = repository.findAll(new PageRequest(1, 20); @@ -135,16 +130,15 @@ Page<User> users = repository.findAll(new PageRequest(1, 20);Next to standard CRUD functionality repositories are usually query the underlying datastore. With Spring Data declaring those queries becomes - a four-step process (we use the JPA based module as example but that works - the same way for other stores): + a four-step process. - Declare an interface extending the technology specific - Repository sub-interface and type it to the domain class it shall - handle. + Declare an interface extending + Repository or one of it's + sub-interfaces and type it to the domain class it shall handle. - public interface PersonRepository extends JpaRepository<User, Long> { … } + public interface PersonRepository extends Repository<User, Long> { … } @@ -194,10 +188,52 @@ Page<User> users = repository.findAll(new PageRequest(1, 20);Defining repository interfaces As a very first step you define a domain class specific repository - interface to start with. It's got to be typed to the domain class and an - ID type so that you get CRUD methods of the - Repository interface tailored to - it. + interface to start with. It's got to extend + Repository and be typed to the domain + class and an ID type. If you want to expose CRUD methods for that domain + type, extend CrudRepository instead of + Repository. + +

+ Fine tuning repository definition + + Usually you will have your repository interface extend + Repository, + CrudRepository or + PagingAndSortingRepository. If you + don't like extending Spring Data interfaces at all you can also + annotate your repository interface with + @RepositoryDefinition. Extending + CrudRepository will expose a complete + set of methods to manipulate your entities. If you rather want to be + selective about the methods being expose simply copy the ones you want + to expose from CrudRepository into your + domain repository. + + + Selectively exposing CRUD methods + + interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> { + T findOne(ID id); + T save(T entity); +} + +interface UserRepository extends MyBaseRepository<User, Long> { + + User findByEmailAddress(EmailAddress emailAddress); +} + + + In the first step we define a common base interface for all our + domain repositories and expose findOne(…) as + well as save(…).These methods will be routed + into the base repository implementation of the store of your choice + because they are matching the method signatures in + CrudRepository. So our + UserRepository will now be able to save + users, find single ones by id as well as triggering a query to find + Users by their email address. +
@@ -271,7 +307,7 @@ Page<User> users = repository.findAll(new PageRequest(1, 20); Query creation from method names - public interface PersonRepository extends JpaRepository<User, Long> { + public interface PersonRepository extends Repository<User, Long> { List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); } @@ -398,10 +434,9 @@ List<User> findByLastname(String lastname, Pageable pageable);In this case we instruct Spring to scan com.acme.repositories and all it's sub packages for - interfaces extending the appropriate - Repository sub-interface (in this case - JpaRepository). For each interface - found it will register the presistence technology specific + interfaces extending Repository or one + of its sub-interfaces. For each interface found it will register the + presistence technology specific FactoryBean to create the according proxies that handle invocations of the query methods. Each of these beans will be registered under a bean name that is derived from the @@ -520,7 +555,7 @@ UserRepository repository = factory.getRepository(UserRepository.class); Changes to the your basic repository interface - public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom { + public interface UserRepository extends CrudRepository<User, Long>, UserRepositoryCustom { // Declare query methods here }Let your standard repository interface extend the custom