Uploaded image for project: 'Spring Data JPA'
  1. Spring Data JPA
  2. DATAJPA-674

Problems following the documentation for adding custom behaviour to all repositories

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Fixed
    • Affects Version/s: 1.7.2 (Evans SR2)
    • Fix Version/s: 1.9 M1 (Gosling)
    • Component/s: Documentation
    • Labels:
      None
    • Environment:
      All

      Description

      I have a very large application using multiple Spring Data modules, including Spring Data JPA. I now have a requirement to add some common logic to all JPA repositories. I tried implementing this by following the documentation. However, I have run into issues.

      1. There is no method called RepositoryMetadata.getDomainClass. There is however a method called RepositoryMetadata.getDomainType. It seems that the documentation needs an update. However, given that SimpleJpaRepository has a similar method called getDomainClass, it would be better for the method names to be consistent.
      2. Having followed the documentation to the tee (except for correcting the method name above), my application failed to start. I have a class @Entity @QueryEntity public class Company and its corresponding repository public interface CompanyRepository extends JpaRepository<Company, String>, QueryDslPredicateExecutor<Company>. The application failed to start with the error Caused by: org.springframework.data.mapping.PropertyReferenceException: No property findAll found for type Company!.

      For the second error I dug into the code for JpaRepositoryFactory. I think that structuring the code as follows will help extending the class more easily.

      public class JpaRepositoryFactory extends RepositoryFactorySupport {
        ...
        protected Class<?> getTargetRepositoryClass() {
          return SimpleJpaRepository.class;
        }
      
        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
          return isQueryDslExecutor(metadata.getRepositoryInterface())
            ? QueryDslJpaRepository.class
            : getTargetRepositoryClass();
        }
      
        protected <R extends SimpleJpaRepository<T, ID>, T, ID extends Serializable> getTargetRepository(JpaEntityInformation<?, Serializable> entityInformation, EntityManager entityManager) {
          return new SimpleJpaRepository(entityInformation, entityManager);
        }
      
        protected <T, ID extends Serializable> SimpleJpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) {
          Class<?> repositoryInterface = metadata.getRepositoryInterface();
          JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
      
         return isQueryDslExecutor(repositoryInterface)
            ? new QueryDslJpaRepository(entityInformation, entityManager)
            : getTargetRepository(entityInformation, entityManager);
        }
        ...
      }
      

      With this foundation in place, my custom code would have greatly simplified to:

      public class MyJpaRepositoryFactory extends JpaRepositoryFactory {
        @Override
        protected Class<?> getTargetRepositoryClass() {
          return MyJpaRepositoryImpl.class;
        }
      
        @Override
        protected <R extends SimpleJpaRepository<T, ID>, T, ID extends Serializable> getTargetRepository(JpaEntityInformation<?, Serializable> entityInformation, EntityManager entityManager) {
          return new MyJpaRepositoryImpl(entityInformation, entityManager);
        }
      }
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              olivergierke Oliver Drotbohm
              Reporter:
              manish.in.java Manish
              Last updater:
              Oliver Drotbohm
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: