javaspringspring-repositories

Is it possible to create a generic repository that extends other interfaces that extend Spring's CrudRepository?


Here are the details:

I have multiple Models in my application, each model has a repository that extends Spring's CrudRepository.

For example:

I would like to create a generic MyApplicationRepository that extends all of my individual repositories so that I need only create a single instance of MyApplicationRepository instead of creating multiple instances of my individual repositories.

I tried this:

public interface MyApplicationRepositoryInterface extends
    EyeColorRepository,
    HairColorRepository,
    StateRepository {
}


public class MyApplicationRepository implements MyApplicationRepositoryInterface {
}

However, when I try to extend all of my individual repositories in MyApplicationRepositoryInterface I get this error:

CrudRepository cannot be inherited with different arguments: <com.myapp.Models.EyeColor, java.lang.Long> and <com.myapp.Models.HairColor, java.lang.Long>

So is there a way to do what I would like to do, or am I stuck with instantiating instances of all my model repositories?


Solution

  • First, I'll try to explain the error you're getting: CrudRepository is a parameterised interface and inheriting from (multiple) CrudRepository interfaces of different parameterised-types is creating a conflict at runtime.

    IMO, what you're trying to do is counter-productive. Spring's data repository provides a type-safe implementation of CRUD methods at runtime, when you extend CrudRepository. This gives you cleaner code, and provides compile-time correctness. And, CrudRepository is already pretty generic - it's better that way (at the interface level, than in implementation).

    Even if you were to create such a repository, you would have to give up the use of CrudRepository and create a single class with all the CRUD methods across all your models (eg. saveEyeColor, saveHairColor, etc). Maybe using something like a SpringTemplate. This isn't the best way to go about it IMO, as you'll be mixing your domain objects and the class will become a nightmare to maintain.

    To answer your question, yes you'll have to inject an individual repository instance for each model.