Spring Jpa добавляет пользовательские функции во все репозитории и в то же время другие пользовательские функции в один репозиторий
Весенняя документация здесь http://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations приведен пример добавления пользовательских функций во все репозитории или в один репозиторий, а не в оба.
предположим, я хочу добавить некоторые пользовательские функции во все репозитории (используя пользовательский репозиторий Factory Bean) и некоторые другие только в один репозиторий (docs говорит использовать пользовательский интерфейс и пользовательский Impl); как я могу этого достичь?
некоторый пример кода, где я добавил метод "setCurrentTenansInSession "ко всем репозиториям; теперь я хочу добавить пользовательский метод, например" newCustomMethod", в ona single repository (это MyJpaRepository, как для моей фабрики пользовательских репозиториев). Как мне это сделать?
пользовательский интерфейс поведения:
@NoRepositoryBean
public interface MyJpaRepository<T, ID extends Serializable> extends JpaRepository<T, ID> { 
    public void setCurrentTenantInSession(Object object);       
}
реализация пользовательского поведения:
public class MultiTenantSimpleJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements MyJpaRepository<T, ID> {
    public void setCurrentTenantInSession(Object object) {
        //custom impl
    }
}
пользовательский репозиторий factory bean :
public class MultiTenantJpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> {
    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new MultiTenantJpaRepositoryFactory(entityManager);
    }
}
и, наконец, фабрика пользовательских репозиториев:
public class MultiTenantJpaRepositoryFactory extends JpaRepositoryFactory {
    public MultiTenantJpaRepositoryFactory(EntityManager entityManager) {
        super(entityManager);
    }
    @Override
    protected JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) {
        final JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
        final SimpleJpaRepository<?, ?> repo = new MultiTenantSimpleJpaRepository(entityInformation, entityManager);
        repo.setLockMetadataProvider(LockModeRepositoryPostProcessor.INSTANCE.getLockMetadataProvider());
        return repo;
    }
    @Override
    protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
        return MultiTenantSimpleJpaRepository.class;
    }
}
1 ответов
вам просто нужно объединить подходы на странице doc, которую вы упомянули. Пусть Car быть объектом, для которого вы хотите иметь пользовательский репозиторий.
CommonCustomRepository определяет методы, добавленные ко всем репозиториям:
@NoRepositoryBean
public interface CommonCustomRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
    String getCustomValue();
}
реализация для этого РЕПО:
public class CommonCustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements CommonCustomRepository<T, ID> {
    public CommonCustomRepositoryImpl(Class<T> domainClass, EntityManager em) {
        super(domainClass, em);
    }
    public CommonCustomRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
            EntityManager entityManager) {
        super(entityInformation, entityManager);
    }
    @Override
    public String getCustomValue() {
        return "CustomValue";
    }
}
пользовательские методы CarRepository
@NoRepositoryBean
public interface CustomCarRepository {
    public String getCustomCarValue();
}
реализация пользовательских методов, связанных с автомобилем
public class CarRepositoryImpl implements CustomCarRepository {
    @PersistenceContext
    private EntityManager em;
    @Override
    public String getCustomCarValue() {
        return "CustomCarValue";
    }
}
комбинированный интерфейс для CarRepository
public interface CarRepository extends CommonCustomRepository<Car, Long>, CustomCarRepository {
}
Custom repo factory, как и в документации
public class CustomRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends
    JpaRepositoryFactoryBean<R, T, I> {
    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new CustomRepositoryFactory(entityManager);
    }
    private static class CustomRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {
        private EntityManager entityManager;
        public CustomRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }
        @Override
        protected Object getTargetRepository(RepositoryMetadata metadata) {
            return new CommonCustomRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager);
        }
        @Override
        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 CommonCustomRepositoryImpl.class;
        }
    }
}
последний бит конфигурации, как и в docs
<jpa:repositories base-package="com.example" factory-class="com.example.CustomRepositoryFactoryBean"/>
