Spring Data JPA – 注入失败 – BeanCreationException:无法自动assembly字段

我按照这里发布的教程获得了一个基础应用程序来使用Spring Data JPA。 现在,我如何理解,使用配置

 

应该导致Spring Data JPA扫描的包用于扩展JpaRepository接口并创建它的JpaRepository bean,因此可以使用简单的Spring @Autowired在我的服务类中的任何地方使用它。 但它失败了,说它无法找到一个带有className的bean(这是bean在创建时获得的默认名称,只需使用去大写的ClassName)。

但是,当我在我的applicationContext中配置bean manualy时,如下所示:

  

Spring能够找到豆子。 我当然得到一个错误,因为我想从一个接口创建一个bean,这显然是行不通的。 但问题是,看起来Spring Data JPA“自动bean创建”似乎以某种方式失败了。

我附上相关代码,以便您查看。 顺便说一句,我应该提一下,我正在开发一个portlet,所以不要奇怪为什么我没有spring-config。 我目前只使用applicationConfig和一个MyPortlet-Portlet.xml进行portlet配置(但这不应该与此问题相关)。 我添加了import语句只是为了确保我没有使用错误的注释/类。

applicationContext.xml中

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

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{ 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的classpath地狱(该死的,这是一个很好的产品)现在我在这里。 希望有人能帮助我。

对可能出现问题的基本解释并且可能更好地理解弹簧自动注射function将是很好的。 我已经阅读了spring文档,但说实话:有很多方法可以配置一些东西,而且我不太明白在选择其中一种配置样式时真正需要什么。

编辑

在尝试更新项目后,我仍然收到错误。 按此处要求更多细节(追踪):

 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.(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.(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.(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) 

编辑#2根据要求添加了applicationContext.xml(包括我根据正在进行的讨论所做的更改)

             classpath*:META-INF/OverridePersistence.xml                    hibernate.dialect=org.hibernate.dialect.MySQLDialect         

问题很可能出在您未显示的某些配置中。 如果你发布了你得到的错误也会很好。 它可能与您认为的不同。

我注意到你的配置有一点是你正在使用context:annotation-config而不是context:component-scan 。 后者将根据@Component注释系列自动检测并创建bean。 前者不这样做。

除此之外,你发布的所有内容看起来都应该有效,不过有几个奇怪的东西,我马上就会来。 我将所有发布的代码复制到一个示例项目中,并填写了一些细节,如maven pom , persistence.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.xmlPersistenceAnnotationBeanPostProcessor 。 它没有为你做任何事情。 当然,可能还有其他需要它的代码,你没有展示过。
  • CustomerService上的@Repository注释应该用于DAO类或与数据库交互的类。 服务的适当注释是@Service
  • ICustomerRepository上的@Resource注释主要用于标记自动assembly的字段和方法 。 我不确定是什么让你认为把它放在你的存储库界面上,但它没有做任何事情。
  • 您的存储库不应该是@Transactional 。 这属于你的服务,你已经在那里,所以没关系。 请注意,它仍然可以与存储库上的@Transactional使用,因为它只是加入了服务启动的现有事务。
  • 值得注意的是,即使您有一个@Component相关的注释(服务上的@Repository ),您也不会使用组件扫描 。 这可能会给你带来一些问题。 我没有打开组件扫描,而是在示例项目中使用XML手动创建了服务bean。

所以……如果你没有向你解释某些事情,如果你给我一个特定的错误,我可以解释你为什么得到它并告诉你如何做到正确。