Spring Boot:如何声明自定义存储库工厂bean

时间:2016-04-19 14:37:54

标签: java spring spring-boot spring-data

我在应用程序上使用带有基于注释的/ JavaConfig配置的 Spring Boot(1.3.3)。 我有以下存储库接口:

@RepositoryRestResource(collectionResourceRel = "something", path = "something")
public interface SomethingRepository 
    extends CrudRepository<SomethingRepository, Long> {

}

我想要做的是覆盖生成的存储库代理中某些方法的行为。我发现这样做的唯一方法是基于文档建议添加新的自定义方法(参见:Adding custom behavior to single repositories),所以我定义了以下接口:

public interface SomethingRepositoryCustom {
    Something findOne(Long id);
}

...我添加了相应的实现:

public SomethingRepositoryImpl extends SimpleJpaRepository<Something, Long> 
    implements SomethingRepositoryCustom {

    public SomethingRepositoryImpl(<Something> domainClass, EntityManager em) {
        super(domainClass, em);
        this.entityManager = em;
    }

    @Override
    public Something findOne(Long id) {
        System.out.println("custom find one");
        // do whatever I want and then fetch the object
        return null;
    }

}

现在,如果我启动应用程序,我会收到以下错误:

  

... org.springframework.beans.BeanInstantiationException:失败   实例化[com.dummy.repositories.SomethingRepositoryImpl]:不   找到默认构造函数;嵌套异常是   java.lang.NoSuchMethodException:   com.dummy.repositories.SomethingRepositoryImpl。()...

问题: 我该如何解决BeanInstantiationException?我假设我需要声明一个存储库工厂bean,但我不知道如何覆盖Spring Boot配置。

2 个答案:

答案 0 :(得分:7)

确实,您必须在@EnableJpaRepositories注释中声明一个新的FactoryBean:

@Configuration
@EnableJpaRepositories(value = "your_package",
        repositoryFactoryBeanClass = CustomFactoryBean.class)
public class ConfigurationClass{}

CustomFactoryBean.java:

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

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new SimpleJpaExecutorFactory(entityManager);
    }

    /**
     * Simple jpa executor factory
     * @param <T>
     * @param <I>
     */
    private static class SimpleJpaExecutorFactory<T, I extends Serializable> extends JpaRepositoryFactory{

        private EntityManager entityManager;

        /**
         * Simple jpa executor factory constructor
         * @param entityManager entity manager
         */
        public SimpleJpaExecutorFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }

        @Override
        protected Object getTargetRepository(RepositoryMetadata metadata) {
            JpaEntityInformation entityInformation =
                    getEntityInformation(metadata.getDomainType());
            return new SomethingRepositoryImpl<T,I>(entityInformation, entityManager);
        }

        @Override
        protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {
            return SomethingRepositoryImpl.class;
        }
    }
}

然后它将是您的SimpleJpaRepository实例:SimpleJpaRepositoryImpl将被使用

答案 1 :(得分:1)

从 1.9 版开始,您不再需要创建新的 FactoryBean 类,而是可以直接设置基础存储库。来自Baeldung

@Configuration
@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao", 
  repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
    // additional JPA Configuration
}

public class ExtendedRepositoryImpl<T, ID extends Serializable>
  extends SimpleJpaRepository<T, ID> implements ExtendedRepository<T, ID> {
    
    private EntityManager entityManager;

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

    // ...
}