In Spring Data project the CrudRepository provides sophisticated CRUD functionality for the entity class that is being managed.
public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> {
<S extends T> S save(S entity);
T findOne(ID primaryKey);
Iterable<T> findAll();
Long count();
void delete(T entity);
boolean exists(ID primaryKey);
// … more functionality omitted.
}
In general, I know what "S extends T" means, i.e. that S, the return type of save operation, must be subtype of T. Why is it necessary to add such as constraint? I think that would be fine doing something like this:
T save (T entity);
As in
void delete(T entity);
I've googled to find more help and I've figured out following question on stackoverflow itself but it isn't really clear for me:
Spring CrudRepository: why to invent a new generic type S
thank you.
If you were to have it as
Then the only variable you could assign the result to would have to be of type
T
.So, if you have a
CrudRepository<Animal,AnimalID> repository
, and you haveYou'd get a compile error - you can't assign the result to
Dog
, as it has to be of typeT
, in this case,Animal
.You'd need to check if the returned value was indeed of type
Dog
, and if so, cast it toDog
to put it insavedDog
.With the declaration as it is, it means that you can assign it to a variable of the same type as the original argument, as type resolution will allow that.
The declaration itself doesn't specify how the non-animal parts of the dog are saved if at all. All it does is allow assigning the result back to a
Dog
if it was originally aDog
.