如何在Spring-Data-JPA中的自定义实现存储库中使用我的基本存储库方法?

时间:2012-07-16 08:44:00

标签: spring-data-jpa

我按照参考指南创建和自定义存储库,并提出了以下内容:

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

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(
        EntityManager entityManager) {

        return new MyBasicRepositoryFactory<T, I>(entityManager);
    }

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

        private EntityManager entityManager;

        public AlisDaoFactory(EntityManager entityManager) {
        super(entityManager);

            this.entityManager = entityManager;
        }

        @Override
        protected Object getTargetRepository(RepositoryMetadata metadata) {

            return new AlisDaoImpl<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 MyBasicRepository.class;
        }
}





@NoRepositoryBean
public interface MyBasicRepository<T extends MyEntity, KEY extends Serializable> extends CrudRepository<T, KEY> {

    void customBaseFoo(T entity);

}

public interface ChildCustomRepository{

    void customChildFoo();
}

public interface ChildRepository extends MyBasicRepository<Child, Integer>, ChildCustomRepository {

    void findByName(String name);
}

现在关于customChildFoo()的实施,我想致电ChildRepository.findByName或甚至MyBasicRepository.customBaseFoo()

这些当然无法访问,因为ChildRepositoryImpl实现ChildCustomRepository而不是ChildRepository,否则我将不得不为基本的CRUD和自定义接口编写实现。

因此我尝试将ChildRepository注入Impl:

public class ChildRepositoryImpl implements ChildCustomRepository{
    @Resource
    private ChildRepository base;

    @Override
    public void customChildFoo(){
        Child child = base.findByName();
        // do some logic with found child here
        base.customBaseFoo(child);            
    }

但由于以下原因导致失败: Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'childDao': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:149) at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:109) at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1442) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:248) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:848) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:790) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707) at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:438) at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416) at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:549) at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303) ... 65 more Caused by: java.lang.NullPointerException at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:125) at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:41) at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142) ... 78 more

那么,如何实现呢?

3 个答案:

答案 0 :(得分:2)

我知道的一个解决方案是在ApplicationContextAware类中实现接口ChildRepositoryImpl并读取像applicationContext.getBean(<bean name>)这样的bean。 我不想实现这个,但这是我现在知道的唯一选择。

答案 1 :(得分:1)

在命名时必须非常小心,以免出现循环引用。

例如,假设您要向其中添加自定义方法

UserDAO

为此,您创建了一个新的存储库接口,称为

UserDAOCust

然后,为了能够在UserDAOCust的实现中使用UserDAO存储库方法,您的实现必须命名为:

UserDAOImpl

并注入UserDAO作为片段的成员。

(通过阅读Spring JPA文档,看来您必须将实现命名为UserDAOCustImpl,但这实际上是在引起循环引用)

完整来源(在Kotlin中):

@Repository
interface UserDAO : CrudRepository<User, Int>, UserDAOCust
{}

interface UserDAOCust
{
    fun findByType(): Optional<List<User>>
}

class UserDAOImpl : UserDAOCust
{
    @Autowired
    private lateinit var userDAO: UCUserDAO

    override fun findByType(): Optional<List<User>>
    {
        // use this.userDAO here
    }
}

答案 2 :(得分:0)

将父存储库注入自定义实现是可以的,它对我有用。但我没有使用任何RepositoryFactoryBean来自定义我的回购。目前使用的是Spring Data JPA 1.3.0,也许您应该尝试使用最新版本。