2

Since I got no answer to my previous question I tried to tweak the example given in the Spring documentation for customizing repositories. There ist a Method getRepository(Class repositoryInterface) which looks like It ist the right place to map my repository Overrides:

public class MyRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
        extends JpaRepositoryFactoryBean<R, T, I> {

    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {

        return new MyRepositoryFactory<>(entityManager);
    }

    private static class MyRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

        private EntityManager entityManager;

        @Resource
        private Map<Class<?>, Class<?>> overrideRepositories;

        public MyRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;

            //Test
            overrideRepositories = new HashMap<>();
            overrideRepositories.put(CustomerRepository.class, Customer2Repository.class);
        }

        protected Object getTargetRepository(RepositoryMetadata metadata) {

            return super.getTargetRepository(metadata);
            // return new MyRepositoryImpl<T, I>((Class<T>)
            // metadata.getDomainClass(), entityManager);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {

            // The RepositoryMetadata can be safely ignored, it is used by the
            // JpaRepositoryFactory
            // to check for QueryDslJpaRepository's which is out of scope.
            return JpaRepository.class;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <E> E getRepository(Class<E> repositoryInterface, Object customImplementation) {
            if (overrideRepositories != null) {
                Class<?> override = overrideRepositories.get(repositoryInterface);
                if (override != null) {
                    repositoryInterface = (Class<E>) override;
                }
            }
            return super.getRepository(repositoryInterface, customImplementation);
        }
    }
}

I configured it like this: @EnableJpaRepositories(repositoryFactoryBeanClass=MyRepositoryFactoryBean.class)

Normally you would autowire the repositories themselves which doesn't work because there are two Interfaces with the same Type and I don't know how to tell Spring which one to use.

If I autowire the factory instead, I can call getRepository each time I need a specific one. But how do I get this factory? Does Spring Data JPA somehow expose this as a bean? I can't find anything on google concerning this. Or is this approach entirely wrong?

Community
  • 1
  • 1
Erik Hofer
  • 2,296
  • 2
  • 18
  • 39

1 Answers1

0

You can use the ApplicationContext instance to get your MyRepositoryFactoryBean bean class. All you have to do is implement the ApplicationContextAware interface in order to get access to the ApplicationContext instance.

  public class myClass implements ApplicationContextAware{
    
        private static ApplicationContext ac;
        
            @Override
            public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
                this.ac = applicationContext;
            }
        
        }

Now you can use ac.getBean("MyRepositoryFactoryBean") to get the factory directly from the ApplicationContext. Once you have that bean you can call getRepository on it.

Maurice
  • 6,698
  • 9
  • 47
  • 104