Spring JPA 2.0 Repository / Factory无法正常工作

时间:2013-05-17 13:16:12

标签: spring jpa spring-data-jpa repository

我正在尝试实现自定义的Java Spring JPA存储库,如Spring documentation中所述。 似乎我的spring配置坚持以标准方式创建存储库,而不是使用给定的MyRepositoryFactoryBean,给我

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.myapp.repository.impl.DocumentRepositoryImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.myapp.repository.impl.DocumentRepositoryImpl.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1006)
... 43 more
Caused by: java.lang.NoSuchMethodException: com.myapp.repository.impl.DocumentRepositoryImpl.<init>()
at java.lang.Class.getConstructor0(Class.java:2730)
at java.lang.Class.getDeclaredConstructor(Class.java:2004)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78)

我正在使用Spring 3.2.2-RELEASE和spring-data-jpa-1.3.2-RELEASE,如果我是正确的,这是最新的。这是我的春季配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"  
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xmlns:jdbc="http://www.springframework.org/schema/jdbc"
   xmlns:util="http://www.springframework.org/schema/util"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">

<import resource="spring-repository-config.xml"/>
<import resource="spring-security-config.xml"/>

<context:component-scan base-package="com.myapp.web.controller"/>
<context:component-scan base-package="com.myapp.webservice.controller"/>

这是spring-repository-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/data/jpa"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:beans="http://www.springframework.org/schema/beans"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">

<repositories base-package="com.myapp.repository"
     factory-class="com.myapp.repository.impl.MyRepositoryFactoryBean"/>
<!-- entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"  -->

如果已在com.myapp.repository.impl.MyRepositoryFactoryBean类的所有方法中添加了调试断点,但这些方法未被调用。

基本界面,就像示例

中一样
package com.myapp.repository.impl;

@NoRepositoryBean
public interface MyRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {

基础实施:

package com.myapp.repository.impl;

@NoRepositoryBean
public class MyRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {

private EntityManager entityManager;

public MyRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
    super(domainClass, entityManager);

    // This is the recommended method for accessing inherited class dependencies.
    this.entityManager = entityManager;
}

public void sharedCustomMethod(ID id) {
    // implementation goes here
}   
}

工厂:

package com.myapp.repository.impl;

import java.io.Serializable;

import javax.persistence.EntityManager;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

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;

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

    protected Object getTargetRepository(RepositoryMetadata metadata) {
        return new MyRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), 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 MyRepositoryImpl.class;
    }
}
}

我的存储库接口定义为:

package com.myapp.repository;

public interface DocumentRepository { // extends MyRepository<Document, Long>

public Document findByDocumentHash(String hashCode);

public Document findById(long id);

}

实施是

package com.myapp.repository.impl;

import java.io.Serializable;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class DocumentRepositoryImpl<Document, ID extends Serializable> extends MyRepositoryImpl<Document, Serializable> {

    private static final long serialVersionUID = 1L;

        public DocumentRepositoryImpl(Class<Document> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
    }

我在控制器中使用这些存储库作为自动引用的参考:

package com.myapp.web.controller;

@Controller
@RequestMapping(value = "/documents")
public class DocumentController {

@Autowired
private DocumentRepository documentRepository;

@RequestMapping(method = RequestMethod.GET)
public ModelAndView list(HttpServletRequest request) {
    this.documentRepository. ...
}

我查看了网络上的各种资源,例如this one,但我无法区分我的代码。任何提示都非常受欢迎!

1 个答案:

答案 0 :(得分:0)

您需要com.myapp.repository.impl.DocumentRepositoryImpl

的默认构造函数
public DocumentRepositoryImpl(){}

Spring首先通过调用默认构造函数(无参数)来实例化您在应用程序上下文中声明的bean(在您的情况下),而不是使用setter来注入其他bean。