Подтвердить что ты не робот

Spring Данные JPA - сбой впрыска - BeanCreationException: Не удалось автополе

i следил за учебником, опубликованным здесь, чтобы получить базовое приложение для работы с Spring данными JPA. Теперь, как я понял, используя конфигурацию

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

должен привести к тому, что пакет будет отсканирован Spring Data JPA для интерфейсов, расширяющих JpaRepository, и создайте конкретизацию bean, чтобы он мог использоваться в любом месте моих классов обслуживания с помощью простого Spring @Autowired. Но он терпит неудачу, заявив, что не может найти bean с именем класса (которое является именем по умолчанию, которое получает bean при создании, просто используя декапитализованное имя класса).

Однако, когда я настраиваю bean manualy в свой applicationContext следующим образом:

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

Spring может найти bean. Я, конечно, получаю сообщение об ошибке, потому что хочу создать bean из интерфейса, который, очевидно, не может работать. НО дело в том, что похоже, что автоматическое создание bean Data JPA "похоже как-то сработало.

Я прикрепил соответствующий код, чтобы вы могли посмотреть на него. Кстати, я должен упомянуть, что я разрабатываю портлет, поэтому не удивляйтесь, почему у меня нет spring -config. В настоящее время я использую только applicationConfig и MyPortlet-Portlet.xml для конфигураций портлетов (но это не должно быть релевантным для этой проблемы). Я добавил операторы импорта, чтобы убедиться, что я не использую неправильные аннотации/классы.

applicationContext.xml

<beans *** ALL MY XMLN and XSI *** />
<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 данных 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 (черт побери, какой продукт с футом **), и теперь я здесь. надеюсь кто-то может мне помочь с этим.

Базовое объяснение того, что беззаботно идет не так, и, возможно, лучшее понимание пружины, функция автоматического впрыска будет отличной. Я прочитал документацию 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.<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)

РЕДАКТИРОВАТЬ # 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" />
4b9b3361

Ответ 1

Проблема, вероятно, связана с некоторыми параметрами, которые вы не указали. Было бы неплохо, если бы вы отправили ошибку, которую вы получаете. Это может быть нечто иное, чем вы думаете.

Одна вещь, которую я замечаю о вашей конфигурации, заключается в том, что вы используете context:annotation-config вместо context:component-scan. Последний будет автоматически определять и создавать beans на основе семейства аннотаций @Component. Первый не делает этого.

Кроме того, все, что вы опубликовали, похоже, должно работать, хотя есть несколько странных вещей, которые я приду в какой-то момент. Я скопировал весь ваш опубликованный код в примерный проект и заполнил несколько деталей, например maven pom, persistence.xml и отсутствующие фрагменты applicationContext.xml. Я также добавил метод "create" для службы, чтобы он действительно что-то сделал. С теми, кто находится на месте, и основным классом, чтобы управлять всем этим, это простой пример. Вы можете просмотреть код на 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

Теперь для странностей, которые я заметил. Сверху:

  • С кодом, указанным здесь, нет необходимости в PersistenceAnnotationBeanPostProcessor, который вы добавили в applicationContext.xml. Это ничего не делает для вас. Конечно, может быть и другой код, который ему нужен, чтобы вы не показывали.
  • Аннотация @Repository на вашем CustomerService должна использоваться для классов DAO или классов, взаимодействующих с базой данных. Соответствующая аннотация для службы @Service.
  • Аннотация @Resource на вашем ICustomerRepository в основном используется для маркировки полей и методов для автообновления. Я не уверен, что заставило вас подумать о том, чтобы поместить его в свой интерфейс репозитория, но он ничего не делает.
  • Ваш репозиторий не должен быть @Transactional. Это к вашим услугам, и вы уже получили его там, так что хорошо. Обратите внимание, что он по-прежнему работает с @Transactional в репозитории, потому что он просто присоединяется к существующей транзакции, запущенной службой.
  • Еще раз стоит отметить, что вы не используете сканирование компонентов, даже если у вас есть аннотация @Component (@Repository на вашей службе), Это может вызвать некоторые проблемы. Вместо включения сканирования компонентов я вручную создал службу bean, используя XML в образце проекта.

Итак... если это вам ничего не объясняет, если вы дадите мне конкретную ошибку, я, вероятно, объясню, почему вы ее получите и расскажите, что делать, чтобы сделать все правильно.