web-dev-qa-db-ja.com

Spring Data JPA-インジェクションに失敗しました-BeanCreationException:フィールドを自動配線できませんでした

here に投稿されたチュートリアルに従って、Spring Data JPAで動作する基本アプリケーションを取得しました。今、私が理解した方法、構成を使用して

<jpa:repositories base-package="my.package.to.scan" />

JpaRepositoryを拡張するインターフェースについてSpring Data JPAがそのパッケージbeeをスキャンし、シンプルなSpring @Autowired。ただし、classNameを持つBeanを見つけることができないため、失敗します(これは、単に大文字を取り除いたClassNameを使用して、作成時にBeanが取得するデフォルト名です)。

ただし、次のようにapplicationContextでBeanを手動で構成すると:

<bean id="ClassName" class="my.package.to.scan.ClassName"/>

春は豆を見つけることができます。インターフェイスからBeanを作成したいので、もちろんエラーになりますが、これは明らかに動作しません。しかし、ポイントは、Spring Data JPAの「自動Bean作成」が何らかの形で失敗するように見えることです。

あなたがそれを見ることができるように、私は関連するコードを添付しました。ところで、私はポートレットを開発していることに言及する必要がありますので、なぜspring-configを持たないのか不思議に思わないでください。現在、ポートレット構成にapplicationConfigのみとMyPortlet-Portlet.xmlを使用しています(ただし、この問題には関係ありません)。間違った注釈/クラスを使用していないことを確認するためだけにimportステートメントを追加しました。

applicationContext.xml

<beans *** ALL MY XMLN's and XSI's *** />
<context:annotation-config />
<jpa:repositories base-package="model.repositories" />

// JPA specific configuration here: dataSource, persistenceUnitManager exceptionTranslator, entityManagerFactory, SessionFactory, transactionManager - should not be relevant for this problem, tell me if i'm wrong

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

ICustomerService-CustomerServiceの単なるインターフェース

import model.entities.Customer;
public interface ICustomerService {
        // example method
    public Customer getCustomer(Long customerId);   
}

CustomerService-ORMデータを取得/設定するためにアプリケーションロジックが使用するクラス

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import model.entities.Customer;
import model.repositories.CustomerRepository;
import model.service.interfaces.ICustomerService;
@Repository
@Transactional(readOnly = true)
public class CustomerService implements ICustomerService{
    @Autowired
    private CustomerRepository repository;

    // example method
    @Override
    public Customer getCustomer(Long customerId){
        return repository.findById(customerId);
    }

CustomerRepository-Spring Data JPAのリポジトリ

import javax.annotation.Resource;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
import model.entities.Customer;
@Resource
@Transactional(readOnly = true)
public interface CustomerRepository extends JpaRepository<Customer, Long>{

    public Customer findById(Long id);
}

顧客-サンプルエンティティ

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Customers")
public class Customer{

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "ID_CUSTOMER")
    private Long    id;

    @Column(name = "dbfirstname")
    private String  firstName;

    @Column(name = "dbname")
    private String  lastName;

    public Long getId(){
        return id;
    }

    public String getFirstName(){
        return firstName;
    }

    public void setFirstName(String firstName){
        this.firstName = firstName;
    }

    public String getLastName(){
        return lastName;
    }

    public void setLastName(String lastName){
        this.lastName = lastName;
    }
}

私はちょうどWebSphereのクラスパスの地獄から来ました(いまいましい、なんて面倒な製品です)、今ここにいます。誰かがこれを手伝ってくれることを願っています。

正確に何がうまくいかないかについての基本的な説明と、おそらくスプリングの自動配線された注入機能についてのより良い理解を提供することは素晴らしいことです。私は春のドキュメントを読みましたが、実を言うと、何かを構成する方法は非常に多く、私にはあまり見えません。構成スタイルの1つを選択するとき、何が本当に必要ですか。

[〜#〜] edit [〜#〜]

プロジェクトを更新しようとしても、エラーが発生します。ここで要求されているように、もう少し詳細(トレース):

Exception created : org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private model.repositories.CustomerRepository model.service.CustomerService.repository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerRepository': FactoryBean threw exception on object creation; nested exception is Java.lang.NullPointerException
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.Java:287)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.Java:1106)
    [...]
        at com.ibm.ws.http.HttpConnection.run(HttpConnection.Java:522)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.Java:1563)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private model.repositories.CustomerRepository model.service.CustomerService.repository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerRepository': FactoryBean threw exception on object creation; nested exception is Java.lang.NullPointerException
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:506)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.Java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.Java:284)
    ... 96 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerRepository': 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:102)
    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.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:478)
    ... 98 more
Caused by: Java.lang.NullPointerException
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.Java:73)
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.Java:115)
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.Java:149)
    at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.Java:1215)
    at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.Java:177)
    at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.Java:89)
    at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.Java:179)
    at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.Java:174)
    at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:48)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
    at Java.lang.reflect.Method.invoke(Method.Java:600)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.Java:376)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.Java:517)
    at $Proxy325.createEntityManager(Unknown Source)

    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.Java:234)
    at $Proxy328.createNamedQuery(Unknown Source)
    at org.springframework.data.jpa.repository.query.NamedQuery.<init>(NamedQuery.Java:74)
    at org.springframework.data.jpa.repository.query.NamedQuery.lookupFrom(NamedQuery.Java:96)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.Java:128)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.Java:162)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.Java:71)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.Java:303)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.Java:157)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.Java:120)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.Java:39)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.Java:142)

EDIT#2必要に応じて追加されたapplicationContext.xml(進行中の議論に基づいて行った変更を含む)

<context:annotation-config />

<jpa:repositories base-package="model.repositories" />

<context:component-scan base-package="model,model.repositories,model.service,controller" />

<bean class="model.service.CustomerService"/>
<bean class="model.service.OrderService"/>
<bean class="model.repositories.CustomerRepository"/>
<bean class="model.repositories.OrderRepository"/>


<bean id="myExceptionTranslator" class="org.springframework.orm.hibernate4.HibernateExceptionTranslator" /> 

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/mydata"
    resource-ref="true" cache="true" />


<bean id="pum"
    class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
    <property name="persistenceXmlLocations">
        <list>
            <value>classpath*:META-INF/OverridePersistence.xml</value>
        </list>
    </property>
    <property name="defaultDataSource" ref="dataSource" />
</bean>


<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="generateDdl" value="true" />
            <property name="database" value="MYSQL" />
        </bean>
    </property>
    <property name="persistenceUnitManager" ref="pum" />
    <property name="persistenceUnitName" value="default" />
</bean>

<bean id="mySessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="model"/>
    <property name="hibernateProperties">
        <value>hibernate.dialect=org.hibernate.dialect.MySQLDialect</value>
    </property>
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    <property name="sessionFactory" ref="mySessionFactory" />
</bean>

<tx:annotation-driven />

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
19
masi

問題は、おそらくあなたが示していない設定のいくつかにあります。取得しているエラーを投稿した場合も良いでしょう。それはあなたが思っているものとは違うかもしれません。

あなたの設定について私が気づく1つのことは、context:annotation-configの代わりにcontext:component-scanを使用しているということです。後者は、アノテーションの@Componentファミリーに基づいてBeanを自動検出して作成します。前者はそうしません。

それ以外は、投稿したすべてが機能するように見えますが、いくつかの奇妙なことがあります。これについてはすぐに説明します。投稿されたすべてのコードをサンプルプロジェクトにコピーし、 maven pompersistence.xml 、および欠落している applicationContext.xml 。また、実際に何かを行うために、サービスに「作成」メソッドを追加しました。それらを適切に配置し、すべてを実行するメインクラスを使用することは、実行可能な例です。 githubでコードを参照 を使用するか、次のコマンドを使用してクローンを作成して実行できます。

git clone git://github.com/zzantozz/testbed tmp
cd tmp/stackoverflow/10539417-basic-spring-data-jpa
mvn -q compile exec:Java -Dexec.mainClass=rds.testbed.springDataJpa.SpringDataJp

さて、私が気づいた奇妙な点について。上から:

  • 与えられたコードでは、applicationContext.xmlに追加した PersistenceAnnotationBeanPostProcessor は不要です。それはあなたのために何もしていません。もちろん、それを必要とする他のコードが表示されていない場合もあります。
  • CustomerServiceの@Repositoryアノテーションは DAOクラスで使用されることを想定 、またはデータベースと対話するクラスです。サービスの適切な注釈は @Service です。
  • ICustomerRepositoryの@Resource注釈は、主に 自動配線用のフィールドとメソッドのマーキングに使用 です。リポジトリインターフェースに配置しようと思われた理由はわかりませんが、そこでは何もしていません。
  • リポジトリは@Transactionalであってはなりません。それはあなたのサービスに属し、あなたはすでにそれをそこに持っているので、それは大丈夫です。サービスによって開始された既存のトランザクションに結合するだけなので、リポジトリの@Transactionalで引き続き機能することに注意してください。
  • @Component関連のアノテーション(サービスの@Repository)がある場合でも、 コンポーネントスキャン を使用していないことに注意してください。それがいくつかの問題を引き起こしている可能性があります。コンポーネントスキャンを有効にする代わりに、サンプルプロジェクトでXMLを使用してサービスBeanを手動で作成しました。

だから...これがあなたに何かを説明していないなら、あなたが私に特定のエラーを与えたなら、おそらくあなたはそれをなぜ得ているのかを説明し、それを正しくするために何をすべきかをあなたに伝えることができます。

20
Ryan Stewart