Skip to content

Introduce List-based repository interfaces #2538

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>3.0.0-SNAPSHOT</version>
<version>3.0.0-2535-list-interfaces-SNAPSHOT</version>

<name>Spring Data Core</name>

Expand Down
4 changes: 3 additions & 1 deletion src/main/asciidoc/repositories.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ For detailed information on the specific features of your module, see the chapte
The central interface in the Spring Data repository abstraction is `Repository`.
It takes the domain class to manage as well as the ID type of the domain class as type arguments.
This interface acts primarily as a marker interface to capture the types to work with and to help you to discover interfaces that extend this one.
The https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html[`CrudRepository`] interface provides sophisticated CRUD functionality for the entity class that is being managed.
The https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html[`CrudRepository`] and https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/ListCrudRepository.html[`ListCrudRepository`] interfaces provide sophisticated CRUD functionality for the entity class that is being managed.

[[repositories.repository]]
.`CrudRepository` Interface
Expand Down Expand Up @@ -55,6 +55,8 @@ public interface CrudRepository<T, ID> extends Repository<T, ID> {
<6> Indicates whether an entity with the given ID exists.
====

`ListCrudRepository` offers equivalent methods, but they return `List` where the `CrudRepository` methods return an `Iterable`.

NOTE: We also provide persistence technology-specific abstractions, such as `JpaRepository` or `MongoRepository`.
Those interfaces extend `CrudRepository` and expose the capabilities of the underlying persistence technology in addition to the rather generic persistence technology-agnostic interfaces such as `CrudRepository`.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright 2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.querydsl;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.query.FluentQuery;

import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;

/**
* Interface to allow execution of QueryDsl {@link Predicate} instances.This identical to *
* {@link QuerydslPredicateExecutor} but returns {@link List} instead of {@link Iterable} where applicable.
*
* @author Jens Schauder
* @since 3.0
* @see QuerydslPredicateExecutor
*/
public interface ListQuerydslPredicateExecutor<T> {

/**
* Returns a single entity matching the given {@link Predicate} or {@link Optional#empty()} if none was found.
*
* @param predicate must not be {@literal null}.
* @return a single entity matching the given {@link Predicate} or {@link Optional#empty()} if none was found.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the predicate yields more than one
* result.
*/
Optional<T> findOne(Predicate predicate);

/**
* Returns all entities matching the given {@link Predicate}. In case no match could be found an empty {@link List} is
* returned.
*
* @param predicate must not be {@literal null}.
* @return all entities matching the given {@link Predicate}.
*/
List<T> findAll(Predicate predicate);

/**
* Returns all entities matching the given {@link Predicate} applying the given {@link Sort}. In case no match could
* be found an empty {@link List} is returned.
*
* @param predicate must not be {@literal null}.
* @param sort the {@link Sort} specification to sort the results by, may be {@link Sort#unsorted()}, must not be
* {@literal null}.
* @return all entities matching the given {@link Predicate}.
*/
List<T> findAll(Predicate predicate, Sort sort);

/**
* Returns all entities matching the given {@link Predicate} applying the given {@link OrderSpecifier}s. In case no
* match could be found an empty {@link List} is returned.
*
* @param predicate must not be {@literal null}.
* @param orders the {@link OrderSpecifier}s to sort the results by, must not be {@literal null}.
* @return all entities matching the given {@link Predicate} applying the given {@link OrderSpecifier}s.
*/
List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);

/**
* Returns all entities ordered by the given {@link OrderSpecifier}s.
*
* @param orders the {@link OrderSpecifier}s to sort the results by, must not be {@literal null}.
* @return all entities ordered by the given {@link OrderSpecifier}s.
*/
List<T> findAll(OrderSpecifier<?>... orders);

/**
* Returns a {@link Page} of entities matching the given {@link Predicate}. In case no match could be found, an empty
* {@link Page} is returned.
*
* @param predicate must not be {@literal null}.
* @param pageable may be {@link Pageable#unpaged()}, must not be {@literal null}.
* @return a {@link Page} of entities matching the given {@link Predicate}.
*/
Page<T> findAll(Predicate predicate, Pageable pageable);

/**
* Returns the number of instances matching the given {@link Predicate}.
*
* @param predicate the {@link Predicate} to count instances for, must not be {@literal null}.
* @return the number of instances matching the {@link Predicate}.
*/
long count(Predicate predicate);

/**
* Checks whether the data store contains elements that match the given {@link Predicate}.
*
* @param predicate the {@link Predicate} to use for the existence check, must not be {@literal null}.
* @return {@literal true} if the data store contains elements that match the given {@link Predicate}.
*/
boolean exists(Predicate predicate);

/**
* Returns entities matching the given {@link Predicate} applying the {@link Function queryFunction} that defines the
* query and its result type.
*
* @param predicate must not be {@literal null}.
* @param queryFunction the query function defining projection, sorting, and the result type
* @return all entities matching the given {@link Predicate}.
*/
<S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright 2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.repository;

import java.util.List;
import java.util.Optional;

/**
* Interface for generic CRUD operations on a repository for a specific type. This identical to {@link CrudRepository}
* but returns {@link List} instead of {@link Iterable} where applicable.
*
* @author Jens Schauder
* @see CrudRepository
* @since 3.0
*/
@NoRepositoryBean
public interface ListCrudRepository<T, ID> extends Repository<T, ID> {

/**
* Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
* entity instance completely.
*
* @param entity must not be {@literal null}.
* @return the saved entity; will never be {@literal null}.
* @throws IllegalArgumentException in case the given {@literal entity} is {@literal null}.
*/
<S extends T> S save(S entity);

/**
* Saves all given entities.
*
* @param entities must not be {@literal null} nor must it contain {@literal null}.
* @return the saved entities; will never be {@literal null}. The returned {@literal Iterable} will have the same size
* as the {@literal Iterable} passed as an argument.
* @throws IllegalArgumentException in case the given {@link Iterable entities} or one of its entities is
* {@literal null}.
*/
<S extends T> List<S> saveAll(Iterable<S> entities);

/**
* Retrieves an entity by its id.
*
* @param id must not be {@literal null}.
* @return the entity with the given id or {@literal Optional#empty()} if none found.
* @throws IllegalArgumentException if {@literal id} is {@literal null}.
*/
Optional<T> findById(ID id);

/**
* Returns whether an entity with the given id exists.
*
* @param id must not be {@literal null}.
* @return {@literal true} if an entity with the given id exists, {@literal false} otherwise.
* @throws IllegalArgumentException if {@literal id} is {@literal null}.
*/
boolean existsById(ID id);

/**
* Returns all instances of the type.
*
* @return all entities
*/
List<T> findAll();

/**
* Returns all instances of the type {@code T} with the given IDs.
* <p>
* If some or all ids are not found, no entities are returned for these IDs.
* <p>
* Note that the order of elements in the result is not guaranteed.
*
* @param ids must not be {@literal null} nor contain any {@literal null} values.
* @return guaranteed to be not {@literal null}. The size can be equal or less than the number of given
* {@literal ids}.
* @throws IllegalArgumentException in case the given {@link Iterable ids} or one of its items is {@literal null}.
*/
List<T> findAllById(Iterable<ID> ids);

/**
* Returns the number of entities available.
*
* @return the number of entities.
*/
long count();

/**
* Deletes the entity with the given id.
*
* @param id must not be {@literal null}.
* @throws IllegalArgumentException in case the given {@literal id} is {@literal null}
*/
void deleteById(ID id);

/**
* Deletes a given entity.
*
* @param entity must not be {@literal null}.
* @throws IllegalArgumentException in case the given entity is {@literal null}.
*/
void delete(T entity);

/**
* Deletes all instances of the type {@code T} with the given IDs.
*
* @param ids must not be {@literal null}. Must not contain {@literal null} elements.
* @throws IllegalArgumentException in case the given {@literal ids} or one of its elements is {@literal null}.
*/
void deleteAllById(Iterable<? extends ID> ids);

/**
* Deletes the given entities.
*
* @param entities must not be {@literal null}. Must not contain {@literal null} elements.
* @throws IllegalArgumentException in case the given {@literal entities} or one of its entities is {@literal null}.
*/
void deleteAll(Iterable<? extends T> entities);

/**
* Deletes all entities managed by the repository.
*/
void deleteAll();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright 2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.repository.query;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

/**
* Interface to allow execution of Query by Example {@link Example} instances. This identical to
* {@link QueryByExampleExecutor} but returns {@link List} instead of {@link Iterable} where applicable.
*
* @param <T> the type of entity for which this executor acts on.
* @author Jens Schauder
* @since 3.0
* @see QueryByExampleExecutor
*/
public interface ListQueryByExampleExecutor<T> {

/**
* Returns a single entity matching the given {@link Example} or {@link Optional#empty()} if none was found.
*
* @param example must not be {@literal null}.
* @return a single entity matching the given {@link Example} or {@link Optional#empty()} if none was found.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the Example yields more than one result.
*/
<S extends T> Optional<S> findOne(Example<S> example);

/**
* Returns all entities matching the given {@link Example}. In case no match could be found an empty {@link List} is
* returned.
*
* @param example must not be {@literal null}.
* @return all entities matching the given {@link Example}.
*/
<S extends T> List<S> findAll(Example<S> example);

/**
* Returns all entities matching the given {@link Example} applying the given {@link Sort}. In case no match could be
* found an empty {@link List} is returned.
*
* @param example must not be {@literal null}.
* @param sort the {@link Sort} specification to sort the results by, must not be {@literal null}.
* @return all entities matching the given {@link Example}.
*/
<S extends T> List<S> findAll(Example<S> example, Sort sort);

/**
* Returns a {@link Page} of entities matching the given {@link Example}. In case no match could be found, an empty
* {@link Page} is returned.
*
* @param example must not be {@literal null}.
* @param pageable can be {@literal null}.
* @return a {@link Page} of entities matching the given {@link Example}.
*/
<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);

/**
* Returns the number of instances matching the given {@link Example}.
*
* @param example the {@link Example} to count instances for. Must not be {@literal null}.
* @return the number of instances matching the {@link Example}.
*/
<S extends T> long count(Example<S> example);

/**
* Checks whether the data store contains elements that match the given {@link Example}.
*
* @param example the {@link Example} to use for the existence check. Must not be {@literal null}.
* @return {@literal true} if the data store contains elements that match the given {@link Example}.
*/
<S extends T> boolean exists(Example<S> example);

/**
* Returns entities matching the given {@link Example} applying the {@link Function queryFunction} that defines the
* query and its result type.
*
* @param example must not be {@literal null}.
* @param queryFunction the query function defining projection, sorting, and the result type
* @return all entities matching the given {@link Example}.
*/
<S extends T, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
}