Spring Data JPA How to build a generic Repository for multiple entities? [duplicate]











up vote
0
down vote

favorite
1













This question already has an answer here:




  • Generic Repository in Spring JPA

    2 answers




I'm beginning to work with Spring Data JPA repositories. We have an application already using Spring MVC (No spring boot or spring data JPA), where we have written a Generic DAO class that handles basic CRUD operations for virtually all entities that we have. Any other special operations can be handled by writing custom DAOs.



Now, Spring data JPA has made things very easy by requiring us to write only an interface and the rest is taken care of.



public interface PersonRepository extends JpaRepository<Person, Long> {

}


This is cool, but I was wondering if I can introduce generics here.



The reason is, my application has a number of entities for which we need to perform only basic CRUD operations and nothing more. Which means, for every entity, we need to write an interface. Though the code is minimal, it results in one file for each entity, which I guess can be avoided (true?).



My question is, can I write a generic Repository class like



public interface GenericRepository<T> extends JpaRepository<T, Long> {

}


so that my service class can look like this



@Autowired
private GenericRepository<Person> personRepository;

public List<Person> findAll() {
return this.personRepository.findAll();
}


This will be a much cleaner approach for basic operations, as one Repository interface handles a number of entities.



EDIT
It turns out that I can indeed create a repository interface as I illustrated above, but when the application starts, I get an error which says



Error creating bean with name 'genericRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class java.lang.Object


This is probably because of the Generic Type



I have to say that my entities are separate classes in themselves and do not implement or extend a super entity/entities. Would it help if they did?



Please guide me in the right direction.



Thanks!










share|improve this question













marked as duplicate by Jens Schauder java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 8 at 15:03


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • what about stackoverflow.com/questions/23812458/… ?
    – Pijotrek
    Nov 8 at 14:15















up vote
0
down vote

favorite
1













This question already has an answer here:




  • Generic Repository in Spring JPA

    2 answers




I'm beginning to work with Spring Data JPA repositories. We have an application already using Spring MVC (No spring boot or spring data JPA), where we have written a Generic DAO class that handles basic CRUD operations for virtually all entities that we have. Any other special operations can be handled by writing custom DAOs.



Now, Spring data JPA has made things very easy by requiring us to write only an interface and the rest is taken care of.



public interface PersonRepository extends JpaRepository<Person, Long> {

}


This is cool, but I was wondering if I can introduce generics here.



The reason is, my application has a number of entities for which we need to perform only basic CRUD operations and nothing more. Which means, for every entity, we need to write an interface. Though the code is minimal, it results in one file for each entity, which I guess can be avoided (true?).



My question is, can I write a generic Repository class like



public interface GenericRepository<T> extends JpaRepository<T, Long> {

}


so that my service class can look like this



@Autowired
private GenericRepository<Person> personRepository;

public List<Person> findAll() {
return this.personRepository.findAll();
}


This will be a much cleaner approach for basic operations, as one Repository interface handles a number of entities.



EDIT
It turns out that I can indeed create a repository interface as I illustrated above, but when the application starts, I get an error which says



Error creating bean with name 'genericRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class java.lang.Object


This is probably because of the Generic Type



I have to say that my entities are separate classes in themselves and do not implement or extend a super entity/entities. Would it help if they did?



Please guide me in the right direction.



Thanks!










share|improve this question













marked as duplicate by Jens Schauder java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 8 at 15:03


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • what about stackoverflow.com/questions/23812458/… ?
    – Pijotrek
    Nov 8 at 14:15













up vote
0
down vote

favorite
1









up vote
0
down vote

favorite
1






1






This question already has an answer here:




  • Generic Repository in Spring JPA

    2 answers




I'm beginning to work with Spring Data JPA repositories. We have an application already using Spring MVC (No spring boot or spring data JPA), where we have written a Generic DAO class that handles basic CRUD operations for virtually all entities that we have. Any other special operations can be handled by writing custom DAOs.



Now, Spring data JPA has made things very easy by requiring us to write only an interface and the rest is taken care of.



public interface PersonRepository extends JpaRepository<Person, Long> {

}


This is cool, but I was wondering if I can introduce generics here.



The reason is, my application has a number of entities for which we need to perform only basic CRUD operations and nothing more. Which means, for every entity, we need to write an interface. Though the code is minimal, it results in one file for each entity, which I guess can be avoided (true?).



My question is, can I write a generic Repository class like



public interface GenericRepository<T> extends JpaRepository<T, Long> {

}


so that my service class can look like this



@Autowired
private GenericRepository<Person> personRepository;

public List<Person> findAll() {
return this.personRepository.findAll();
}


This will be a much cleaner approach for basic operations, as one Repository interface handles a number of entities.



EDIT
It turns out that I can indeed create a repository interface as I illustrated above, but when the application starts, I get an error which says



Error creating bean with name 'genericRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class java.lang.Object


This is probably because of the Generic Type



I have to say that my entities are separate classes in themselves and do not implement or extend a super entity/entities. Would it help if they did?



Please guide me in the right direction.



Thanks!










share|improve this question














This question already has an answer here:




  • Generic Repository in Spring JPA

    2 answers




I'm beginning to work with Spring Data JPA repositories. We have an application already using Spring MVC (No spring boot or spring data JPA), where we have written a Generic DAO class that handles basic CRUD operations for virtually all entities that we have. Any other special operations can be handled by writing custom DAOs.



Now, Spring data JPA has made things very easy by requiring us to write only an interface and the rest is taken care of.



public interface PersonRepository extends JpaRepository<Person, Long> {

}


This is cool, but I was wondering if I can introduce generics here.



The reason is, my application has a number of entities for which we need to perform only basic CRUD operations and nothing more. Which means, for every entity, we need to write an interface. Though the code is minimal, it results in one file for each entity, which I guess can be avoided (true?).



My question is, can I write a generic Repository class like



public interface GenericRepository<T> extends JpaRepository<T, Long> {

}


so that my service class can look like this



@Autowired
private GenericRepository<Person> personRepository;

public List<Person> findAll() {
return this.personRepository.findAll();
}


This will be a much cleaner approach for basic operations, as one Repository interface handles a number of entities.



EDIT
It turns out that I can indeed create a repository interface as I illustrated above, but when the application starts, I get an error which says



Error creating bean with name 'genericRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class java.lang.Object


This is probably because of the Generic Type



I have to say that my entities are separate classes in themselves and do not implement or extend a super entity/entities. Would it help if they did?



Please guide me in the right direction.



Thanks!





This question already has an answer here:




  • Generic Repository in Spring JPA

    2 answers








java generics spring-data-jpa






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 8 at 14:04









sriramsridharan

180417




180417




marked as duplicate by Jens Schauder java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 8 at 15:03


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.






marked as duplicate by Jens Schauder java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 8 at 15:03


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • what about stackoverflow.com/questions/23812458/… ?
    – Pijotrek
    Nov 8 at 14:15


















  • what about stackoverflow.com/questions/23812458/… ?
    – Pijotrek
    Nov 8 at 14:15
















what about stackoverflow.com/questions/23812458/… ?
– Pijotrek
Nov 8 at 14:15




what about stackoverflow.com/questions/23812458/… ?
– Pijotrek
Nov 8 at 14:15












1 Answer
1






active

oldest

votes

















up vote
0
down vote













I think you could do it like this:



@NoRepositoryBean
public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
//added custom common functionality for all the GenericRepository implementations
public List<T> findByAttributeContainsText(String attributeName, String text);
}

public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
implements GenericRepository<T, ID> {

private EntityManager entityManager;

public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
}

@Transactional
public List<T> findByAttributeContainsText(String attributeName, String text) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> cQuery = builder.createQuery(getDomainClass());
Root<T> root = cQuery.from(getDomainClass());
cQuery.select(root).where(builder.like(root.<String>get(attributeName), "%" + text + "%"));
TypedQuery<T> query = entityManager.createQuery(cQuery);
return query.getResultList();
}
}
public interface MyOtherRepository extends GenericRepository<Role, Long> {

}


And in your config class:



@Configuration
@EnableJpaRepositories(basePackages="com.myProject", repositoryBaseClass =
GenericRepositoryImpl.class)
public class JpaConfig {

}





share|improve this answer




























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    I think you could do it like this:



    @NoRepositoryBean
    public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
    //added custom common functionality for all the GenericRepository implementations
    public List<T> findByAttributeContainsText(String attributeName, String text);
    }

    public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
    implements GenericRepository<T, ID> {

    private EntityManager entityManager;

    public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    this.entityManager = entityManager;
    }

    @Transactional
    public List<T> findByAttributeContainsText(String attributeName, String text) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<T> cQuery = builder.createQuery(getDomainClass());
    Root<T> root = cQuery.from(getDomainClass());
    cQuery.select(root).where(builder.like(root.<String>get(attributeName), "%" + text + "%"));
    TypedQuery<T> query = entityManager.createQuery(cQuery);
    return query.getResultList();
    }
    }
    public interface MyOtherRepository extends GenericRepository<Role, Long> {

    }


    And in your config class:



    @Configuration
    @EnableJpaRepositories(basePackages="com.myProject", repositoryBaseClass =
    GenericRepositoryImpl.class)
    public class JpaConfig {

    }





    share|improve this answer

























      up vote
      0
      down vote













      I think you could do it like this:



      @NoRepositoryBean
      public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
      //added custom common functionality for all the GenericRepository implementations
      public List<T> findByAttributeContainsText(String attributeName, String text);
      }

      public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
      implements GenericRepository<T, ID> {

      private EntityManager entityManager;

      public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
      super(entityInformation, entityManager);
      this.entityManager = entityManager;
      }

      @Transactional
      public List<T> findByAttributeContainsText(String attributeName, String text) {
      CriteriaBuilder builder = entityManager.getCriteriaBuilder();
      CriteriaQuery<T> cQuery = builder.createQuery(getDomainClass());
      Root<T> root = cQuery.from(getDomainClass());
      cQuery.select(root).where(builder.like(root.<String>get(attributeName), "%" + text + "%"));
      TypedQuery<T> query = entityManager.createQuery(cQuery);
      return query.getResultList();
      }
      }
      public interface MyOtherRepository extends GenericRepository<Role, Long> {

      }


      And in your config class:



      @Configuration
      @EnableJpaRepositories(basePackages="com.myProject", repositoryBaseClass =
      GenericRepositoryImpl.class)
      public class JpaConfig {

      }





      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote









        I think you could do it like this:



        @NoRepositoryBean
        public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
        //added custom common functionality for all the GenericRepository implementations
        public List<T> findByAttributeContainsText(String attributeName, String text);
        }

        public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
        implements GenericRepository<T, ID> {

        private EntityManager entityManager;

        public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
        }

        @Transactional
        public List<T> findByAttributeContainsText(String attributeName, String text) {
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<T> cQuery = builder.createQuery(getDomainClass());
        Root<T> root = cQuery.from(getDomainClass());
        cQuery.select(root).where(builder.like(root.<String>get(attributeName), "%" + text + "%"));
        TypedQuery<T> query = entityManager.createQuery(cQuery);
        return query.getResultList();
        }
        }
        public interface MyOtherRepository extends GenericRepository<Role, Long> {

        }


        And in your config class:



        @Configuration
        @EnableJpaRepositories(basePackages="com.myProject", repositoryBaseClass =
        GenericRepositoryImpl.class)
        public class JpaConfig {

        }





        share|improve this answer












        I think you could do it like this:



        @NoRepositoryBean
        public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
        //added custom common functionality for all the GenericRepository implementations
        public List<T> findByAttributeContainsText(String attributeName, String text);
        }

        public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
        implements GenericRepository<T, ID> {

        private EntityManager entityManager;

        public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
        }

        @Transactional
        public List<T> findByAttributeContainsText(String attributeName, String text) {
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<T> cQuery = builder.createQuery(getDomainClass());
        Root<T> root = cQuery.from(getDomainClass());
        cQuery.select(root).where(builder.like(root.<String>get(attributeName), "%" + text + "%"));
        TypedQuery<T> query = entityManager.createQuery(cQuery);
        return query.getResultList();
        }
        }
        public interface MyOtherRepository extends GenericRepository<Role, Long> {

        }


        And in your config class:



        @Configuration
        @EnableJpaRepositories(basePackages="com.myProject", repositoryBaseClass =
        GenericRepositoryImpl.class)
        public class JpaConfig {

        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 8 at 14:16









        SoftwareTheory

        5452722




        5452722















            這個網誌中的熱門文章

            Xamarin.form Move up view when keyboard appear

            Post-Redirect-Get with Spring WebFlux and Thymeleaf

            Anylogic : not able to use stopDelay()