【问题标题】:Spring Data JPA (CrudRepository) - BeanCreationException: Could not autowire fieldSpring Data JPA (CrudRepository) - BeanCreationException:无法自动装配字段
【发布时间】:2015-08-07 19:01:51
【问题描述】:

我正在尝试使用没有任何实现的 Spring Data JPA - CrudRepository 使用(所有默认选项)。

我的代码出现了这个异常:

线程“主”org.springframework.beans.factory.BeanCreationException 中的异常:创建名为“springJpaContactService”的 bean 时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 com.sample.hibernate.ContactRepository com.sample.hibernate.RepositoryContactServiceImpl.contactRepository;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名为“contactRepository”的 bean 时出错:调用 init 方法失败;嵌套异常是 java.lang.AbstractMethodError: org.springframework.data.repository.core.support.RepositoryFactorySupport.getTargetRepository(Lorg/springframework/data/repository/core/RepositoryInformation;)Ljava/lang/Object; 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) 在 com.sample.hibernate.HibernateJpaApplication.main(HibernateJpaApplication.java:15)

我的班级负责 CrudRepository:

ContactRepository

package com.sample.hibernate;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

public interface ContactRepository extends CrudRepository<Contact, Long> {

    List<Contact> findByFirstName(String firstName);

    List<Contact> findByFirstNameAndLastName(String firstName, String lastName);

}

RepositoryContactService

package com.sample.hibernate;

import java.util.List;

public interface RepositoryContactService {
    List<Contact> findAll();

    List<Contact> findByFirstName(String firstName);

    List<Contact> findByFirstNameAndLastName(String firstName, String lastName);
}

RepositoryContactServiceImpl

package com.sample.hibernate;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;

@Service("springJpaContactService")
@Repository
@Transactional
public class RepositoryContactServiceImpl implements RepositoryContactService {
    @Autowired
    private ContactRepository contactRepository;

    @Transactional(readOnly = true)
    public List<Contact> findAll() {
        return Lists.newArrayList(contactRepository.findAll());
    }

    @Transactional(readOnly = true)
    public List<Contact> findByFirstName(String firstName) {
        return contactRepository.findByFirstName(firstName);
    }

    @Transactional(readOnly = true)
    public List<Contact> findByFirstNameAndLastName(String firstName,
            String lastName) {
        return contactRepository
                .findByFirstNameAndLastName(firstName, lastName);
    }

}

联系方式

package com.sample.hibernate;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityResult;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;

@Entity
@Table(name = "contact")
@NamedQueries({
        @NamedQuery(name="Contact.findAll", query="select c from Contact c"),
        @NamedQuery(name = "Contact.findAllWithDetail", query = "select distinct c from Contact c left join fetch c.contactTelDetails t left join fetch c.hobbies h"),
        @NamedQuery(name = "Contact.findById", query = "select distinct c from Contact c left join fetch c.contactTelDetails t left join fetch c.hobbies h where c.id = :id") })
@SqlResultSetMapping(name="contactResult", entities=@EntityResult(entityClass=Contact.class)
)
public class Contact implements Serializable {

    private static final long serialVersionUID = -8008307767408320097L;
    private Long id;
    private int version;
    private String firstName;
    private String lastName;
    private Date birthDate;
    private Set<ContactTelDetail> contactTelDetails = new HashSet<ContactTelDetail>();
    private Set<Hobby> hobbies = new HashSet<Hobby>();

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Version
    @Column(name = "VERSION")
    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    @Column(name = "FIRST_NAME")
    public String getFirstName() {
        return firstName;
    }

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

    @Column(name = "LAST_NAME")
    public String getLastName() {
        return lastName;
    }

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

    @Temporal(TemporalType.DATE)
    @Column(name = "BIRTH_DATE")
    public Date getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }

    @OneToMany(mappedBy = "contact", cascade = CascadeType.ALL, orphanRemoval = true)
    public Set<ContactTelDetail> getContactTelDetails() {
        return contactTelDetails;
    }

    public void setContactTelDetails(Set<ContactTelDetail> contactTelDetails) {
        this.contactTelDetails = contactTelDetails;
    }

    public void addContactTelDetail(ContactTelDetail contactTelDetail) {
        contactTelDetail.setContact(this);
        getContactTelDetails().add(contactTelDetail);
    }

    public void removeContactTelDetail(ContactTelDetail contactTelDetail) {
        getContactTelDetails().remove(contactTelDetail);
    }

    @ManyToMany
    @JoinTable(name = "contact_hobby_detail", joinColumns = @JoinColumn(name = "CONTACT_ID"), inverseJoinColumns = @JoinColumn(name = "HOBBY_ID"))
    public Set<Hobby> getHobbies() {
        return hobbies;
    }

    public void setHobbies(Set<Hobby> hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    public String toString() {
        return "Contact [id=" + id + ", version=" + version + ", firstName="
                + firstName + ", lastName=" + lastName + ", birthDate="
                + birthDate + "]";
    }

}

app-config.xml

<?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:p="http://www.springframework.org/schema/p"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

    <jdbc:embedded-database id="dataSource" type="H2">
        <jdbc:script location="classpath:sql/schema.sql" />
        <jdbc:script location="classpath:sql/test-data.sql" />
    </jdbc:embedded-database>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="emf" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <bean id="emf"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="packagesToScan" value="com.sample.hibernate" />
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.jdbc.fetch_size">50</prop>
                <prop key="hibernate.jdbc.batch_size">10</prop>
                <prop key="hibernate.show_sql">false</prop>
            </props>
        </property>
    </bean>

    <context:component-scan base-package="com.sample.hibernate" />

    <jpa:repositories base-package="com.sample.hibernate"
        entity-manager-factory-ref="emf" transaction-manager-ref="transactionManager" />
</beans>

我很乐意提供任何线索。这个例子来自一本书,我已经用它 + 在线教程检查了 3 次,但我不知道为什么它没有按预期工作......

【问题讨论】:

    标签: java spring hibernate jpa orm


    【解决方案1】:

    带有注释的一切都很好 - 无需将 @Repository 移动到 ContactRepository。这是因为 ContactRepository 扩展了 CrudRepository,它告诉 Spring 他可以使用 RepositoryContactServiceImpl 中的引用自动装配。问题出在 maven 配置中(因为您的想法是正确的并感谢您)。我改变了:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.0.M2</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.0.2.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    

    现在存储库按预期工作。

    【讨论】:

      【解决方案2】:

      您的@Repository 注释放错了位置。您的ContactRepository 类应该是带有@Repository 注释的类。

      Spring 无法自动连接您的 ContactRepository,因为它不是由 Spring 管理的,因为您没有使用 @Repository 对其进行注释。

      此外,您的RepositoryContactServiceImpl 上有@Transactional,这将使该类中的所有公共方法都具有事务性,因此将@Transactional 放在该类中的每个方法上是多余的。如果您需要每个方法具有不同的事务行为,您可以在每个方法上留下@Transactional 注释,并针对每个方法进行修改以满足您的需要。然后你可以从类中删除@Transactional

      但是,如果每个方法都需要相同类型的事务,如提供的示例中那样,您可以从每个方法中删除 @Transactional 注释,并将 @Transactional 保留在类级别,并指定您的 readOnly那里的财产。

      【讨论】:

      • 我完全同意你对@Transactional 的看法——这只是为了测试目的。
      • 我将 @Repository 添加到 ContactRepository 但它仍然失败(同样的例外)。不需要 ContactRepository 的实现,因为它应该与 CrudRepository 一起提供,对吗?我今天花了 3 个小时与这个例子作斗争,但我不知道出了什么问题..
      • 你从RepositoryContactServiceImpl中删除了@Repository
      • 正确。 RepositoryContactServiceImpl 只有@Service("springJpaContactService")。 ContactRepository 有@Repository,ContactService 没有任何注释。
      • 你仍然收到BeanCreationException: Could not autowire field: private com.sample.hibernate.ContactRepository
      猜你喜欢
      • 2012-05-19
      • 1970-01-01
      • 1970-01-01
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 2014-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多