1
votes

I'm trying to use Spring Data with JPA in such way that it could be possible to easily switch to MongoDB. I am using Spring Boot with default settings i.e. Hibernate ORM, spring-boot-starter-data-jpa.

I have following interface which I want to be common for different providers:

public interface SurveyData {

    @Id
    Long getId();
    void setId(Long id);

    List<QuestionData> getQuestions();
    void setQuestions(List<? extends QuestionData> questions);

}

I have entity implementation.

@Entity
@Table(name="sus_survey")
public class JpaSurveyData implements SurveyData {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "sus_survey_seq")
    @SequenceGenerator(name = "sus_survey_seq", sequenceName = "sus_survey_seq")
    private Long id;

    @Version
    private Long version;

    @OneToMany(mappedBy="owningSurvey")
    private List<JpaQuestionData> questions;

    //.... setters/getters
}

I would like to inject in my beans repository implementing following interface:

@NoRepositoryBean
public interface SurveyDataRepository extends PagingAndSortingRepository<SurveyData, Long> {}

But I would like to not expose any information about JPA entity classes (with @Version field etc.) i.e. behave like JpaRepository but injected as PagingAndSortingRepository:

@Repository
public interface JpaSurveyDataRepository extends JpaRepository<JpaSurveyData, Long> {}

I tried two approaches

  1. SurveyDataRepository has generic type and JpaSurveyDataRepository extends SurveyDataRepository with JPA type as generic:

    public interface SurveyDataRepository<T extends SurveyData> extends PagingAndSortingRepository<SurveyData, Long> {}
    
    @Repository("surveyDataRepository")
    public interface JpaSurveyDataRepository extends SurveyDataRepository<JpaSurveyData> {}
    

    I try to @Autowire them with:

    @Autowired
    private SurveyDataRepository<SurveyData> surveyDataRepository;
    

    That gives me:

    No qualifying bean of type [com.xyz.SurveyDataRepository] found for dependency.
    
  2. Similar to first approach, but I was trying to use SurveyData instead JpaSurveyData:

    @Repository("surveyDataRepository")
    public interface JpaSurveyDataRepository extends SurveyDataRepository<SurveyData> {}
    

    Result is:

    Not an managed type: interface com.xyz.SurveyData
    

Any ideas how to solve it? Or maybe something is missing. The only solution that I see is to wrap repository into own class but I would like to avoid that.

1

1 Answers

0
votes

I am not very sure I understand your problem. Sorry if I don't.

Is this what you want? You have an interface(or abstract class) SurveyData, and class JpaSurveyData to implement it.
You want to have an interface A with SurveyData, and some repository to extend A.

If I am right, this is my working solution:

@NoRepositoryBean
public interface AbstractSurveyDataRepository<T extends SurveyData, ID extends Serializable> extends JpaRepository<T, ID> {
  T findOneBySomeId(Long someId); // you can add some common function here.
}

Then implemented repository is:

public interface JPASurveyDataRepository extends AbstractSurveyDataRepository<JPASurveyData, Long> {
    JPASurveyData findOneBySomeField(Long someField);
}

Then in your service, you can autowire JPASurveyDataRepository to use it.