2014-07-21 2 views
1

스프링 애플 리케이션에 별 문제가 없습니다. 것으로, 문제는 스프링 주석 : @Component works, @Repository does not

import com.maciej.Config; 
import com.maciej.entities.Etwas; 
import com.maciej.services.EtwasService; 
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 
import org.springframework.stereotype.Component; 

@Component 
public class Test { 
    public static void main(String[] args){ 
     AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(Config.class); 
     Etwas etwas = acac.getBean("etwas", Etwas.class); 
     etwas.setSth("STATATASTAT"); 

     EtwasService etwasService = acac.getBean("etwasService", EtwasService.class); 
     for(int i=0; i<=20; i++){ 
      etwasService.save(etwas); 
     } 

     System.out.println(etwasService.read(7).toString()); 

     System.out.println(etwas.getSth()); 
    } 
} 

입니다

:

내 간단한 서비스 클래스 (저장소) 여기

import com.maciej.entities.Etwas; 
import com.maciej.repository.EtwasRepository; 
import org.springframework.stereotype.Component; 
import org.springframework.stereotype.Repository; 

import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.persistence.TypedQuery; 
import java.util.List; 

HERE IS THE PROBLEM ----- @Component works, while @Repository doesn't 
public class EtwasHibernateRepository implements EtwasRepository { 
    @PersistenceContext 
    private EntityManager entityManager; 

    @Override 
    public List<Etwas> findAll() { 
     return null; 
    } 

    @Override 
    public Etwas create(Etwas etwas) { 
     entityManager.persist(etwas); 
     return etwas; 
    } 

    @Override 
    public Etwas read(int id) { 
     TypedQuery<Etwas> query = entityManager.createQuery("SELECT e FROM Etwas e WHERE e.id=:id", Etwas.class); 
     query.setParameter("id", id); 
     Etwas etwas = query.getSingleResult(); 
     return etwas; 
    } 

    @Override 
    public Etwas update(Etwas etwas) { 
     return null; 
    } 

    @Override 
    public boolean delete(int id) { 
     return false; 
    } 
} 

됩니다

:

import com.maciej.entities.Etwas; 
import com.maciej.repository.impl.EtwasHibernateRepository; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 
import org.springframework.transaction.annotation.Transactional; 

@Service 
@Transactional 
public class EtwasService { 
    @Autowired 
    private EtwasHibernateRepository etwasHibernateRepository; 

    public boolean save(Etwas etwas){ 
     etwasHibernateRepository.create(etwas); 
     return true; 
    } 

    public Etwas read(int id){ 
     return etwasHibernateRepository.read(id); 
    } 
} 

간단한 테스트 클래스는 여기에 내 코드입니다 에 @Component으로 주석을 달면 모든 것이 잘 동작합니다. 추가 할 때 실제로 apoperly - @Repository annotation stacktrace : 내가 뭘 잘못했는지 애니 제안이 있니?

PS 코드입니다 정말 간단, 단지 테스트 그래서 :)

스레드에서

예외 "주" org.springframework.beans.factory.BeanCreationException에 대해주의를 해달라고에 대한 혼란 및 제작 : 오류 이름이 'etwasService'인 빈을 생성 : autowired 종속성의 주입이 실패했습니다. 상자의 예외는 org.springframework.beans.factory.BeanCreationException입니다 : 수 없습니다 자동으로 묶어 필드 : 개인 com.maciej.repository.impl.EtwasHibernateRepository com.maciej.services.EtwasService.etwasHibernateRepository; 자동으로 묶어 위한 후보로서 자격이 예상 적어도 1 빈 : 종속성 검색 결과 형 [com.maciej.repository.impl.EtwasHibernateRepository] 없음 적격 콩 : 중첩 예외이다 org.springframework.beans.factory.NoSuchBeanDefinitionException 이 종속성. 종속성 주석 : 조직에서 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues ​​(AutowiredAnnotationBeanPostProcessor.java:292) 에서 {org.springframework.beans.factory.annotation.Autowired @는 (= TRUE 필수)} 된 org.springframework.beans에서 .springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean (AbstractAutowireCapableBeanFactory.java:537)에서 (AbstractAutowireCapableBeanFactory.java:1185) .factory.support.AbstractAutowireCapableBeanFactory.createBean (AbstractAutowireCapableBeanFactory.java:475) 의 org.springframework.beans.factory.support.AbstractBeanFactory $ 1.getObject org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton (DefaultSingletonBeanRegistry.java:228)에서 (AbstractBeanFactory.java:304) 조직 에서. springframework.beans.factory.support.AbstractBeanFactory.doGetBean org.springframework.beans.factory.support.AbstractBeanFactory.getBean (AbstractBeanFactory.java:195)에서 (AbstractBeanFactory.java:300) 된 org.springframework.beans에서 . 팩토리 스니핑 nFactoryInitialization (AbstractApplicationContext.java:760) at org.springframework.context.support.AbstractApplicationContext.refresh org.springframework.context.annotation.AnnotationConfigApplicationContext에서 (AbstractApplicationContext.java:482) . (AnnotationConfigApplicationContext.java:84) com.maciej.test.Test.main (시험에서 . 자바 : 12) sun.reflect.DelegatingMethodAccessorImpl.invoke에서 sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:57) 에서 sun.reflect.NativeMethodAccessorImpl.invoke0 (기본 방법) (DelegatingMethodAccessorImpl.java:43)에서 at java.lang.reflect.Method.invoke (Method.java:606) at com.intellij.rt.execution.application.AppMain.main (AppMain.java:134) 에 의해 발생 : org.springframework.beans. factory.Bean CreationException : 필드를 autowire 할 수 없습니다. private com.maciej.repository.impl.EtwasHibernateRepository com.maciej.services.EtwasService.etwasHibernateRepository; 자동으로 묶어 위한 후보로서 자격이 예상 적어도 1 빈 : 종속성 검색 결과 형 [com.maciej.repository.impl.EtwasHibernateRepository] 없음 적격 콩 : 중첩 예외이다 org.springframework.beans.factory.NoSuchBeanDefinitionException 이 종속성. 종속성 주석 : 에서 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject (AutowiredAnnotationBeanPostProcessor.java:508) 에서 {org.springframework.beans.factory.annotation.Autowired @는 (= TRUE 필수)} org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues ​​(AutowiredAnnotationBeanPostProcessor.java:289) ... (17) 이상에서 org.springframework.beans.factory.annotation.InjectionMetadata.inject (InjectionMetadata.java:87) 발생 원인 : org.springframework.beans.factory.NoSuchBeanDefinitionException : 아니요 [com.maciej.r] 형식의 적격 콩 epository.impl.EtwasHibernateRepository]이 (가) 에 종속 됨 : autowire로 간주되는 적어도 하나의 bean이 종속성에 대한 후보가 입니다. 종속성 주석 : 조직에서 org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException (DefaultListableBeanFactory.java:1103) 에서 {@ org.springframework.beans.factory.annotation.Autowired는 (= TRUE 필수)} 된 org.springframework.beans에서 .springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency (DefaultListableBeanFactory.java:858)에서 (DefaultListableBeanFactory.java:963) .factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject (AutowiredAnnotationBeanPostProcessor.java:480) ... 19 더 많은

업데이트 : 구성

import com.maciej.entities.Etwas; 
import org.apache.commons.dbcp.BasicDataSource; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; 
import org.springframework.orm.jpa.JpaTransactionManager; 
import org.springframework.orm.jpa.JpaVendorAdapter; 
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; 
import org.springframework.transaction.PlatformTransactionManager; 
import org.springframework.transaction.annotation.EnableTransactionManagement; 

import javax.persistence.EntityManagerFactory; 
import java.util.Properties; 

@Configuration 
@ComponentScan 
@EnableTransactionManagement 
public class Config { 
    @Bean 
    public Etwas etwas(){ 
     return new Etwas(); 
    } 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ 
     LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
     emf.setDataSource(dataSource()); 
     emf.setPackagesToScan(new String[]{"com.maciej.entities"}); 

     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     emf.setJpaVendorAdapter(vendorAdapter); 
     emf.setJpaProperties(additionalProperties()); 
     return emf; 
    } 

    @Bean 
    public BasicDataSource dataSource(){ 
     BasicDataSource bds = new BasicDataSource(); 
     bds.setUsername("root"); 
     bds.setPassword("maciek"); 
     bds.setUrl("jdbc:mysql://localhost:3306/test"); 
     bds.setDriverClassName("com.mysql.jdbc.Driver"); 
     return bds; 
    } 


    private Properties additionalProperties(){ 
     Properties properties = new Properties(); 
     properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); 
     properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect"); 
     properties.setProperty("hibernate.show_sql", "true"); 
     properties.setProperty("hibernate.format_sql", "true"); 
     return properties; 
    } 


    @Bean 
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){ 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(emf); //entityManagerFactory().getObject() 
     return transactionManager; 
    } 

    @Bean 
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){ 
     return new PersistenceExceptionTranslationPostProcessor(); 
    } 

} 

답변

1

문제는 당신이 인터페이스 프로그래밍하지 않는다는 사실에있다.

@Service 
@Transactional 
public class EtwasService { 

    @Autowired 
    private EtwasHibernateRepository etwasHibernateRepository; 

autowired 종속성은 완전 구현 클래스의 것이지만 EtwasRepository이어야합니다. 이렇게하면 @Component@Repository에 모두 적용됩니다. 그 옆에 그것은 또한 그것을하는 적당한 방법이다.@Repository 주석

@Service 
@Transactional 
public class EtwasService { 

    @Autowired 
    private EtwasRepository etwasHibernateRepository; 

콩은 자동 예외 변환이 가능하고이 AOP에 적용해야합니다. 기본적으로 Spring은 인터페이스 기반의 JDK 동적 프록시를 사용합니다. EtwasRepository 인터페이스를 구현하는 동적 클래스를 생성하고 aop 인터셉터를 적용합니다. 이렇게하면 EtwasRepository 유형의 bean이되며 더 이상 EtwasHibernateRepository 유형이 아닙니다.

이 변환은 콩에 주석을다는 경우 적용되지 않습니다. @Component.

구성에 대한 참고로 명시적인 선언은 PersistenceExceptionTranslationPostProcessor 일 필요는 없습니다. 그것은 이미 처리되었습니다.

+0

그래서 지금 나는 몇 가지 질문을하고 싶습니다 : 1.What에 대해 @ 서비스? 인터페이스 구현없이 서비스 클래스가 생겼고 @Service가 작동합니다. 2. 봄과 jpa에서 꽤 새로 왔고 실제로 몰랐다. 예외 번역은 무엇을 하는가? 3. 서비스 및 저장소와 "인터페이스가있는 코드"둘 다에 대한 인터페이스를 생성해야합니까? – azalut

+0

'@ Service'에는 현재 추가 동작이 적용되지 않았습니다. 당신의'@ Transactional'은 당신이 인터페이스를 구현하지 않는다는 사실 때문에 cglib 프록시 (클래스 기반)가 생성 될 것입니다. 일반적으로 나는 클래스에 대한 인터페이스를 선호하지만 많은 것들이 10 명의 개발자에게 물어보고 12 개의 답변을 얻습니다. :). –

+0

하지만 인터페이스 프로그래밍에서 한 가지 궁금한 점이 있습니다. 스프링 MVC를 보면서 @Controller @ Services 및 @ Repositories가 있습니다. @ 컨트롤러는 @ Service를 호출하고 @ Service는 @ Repository를 호출해야합니다. 그래서 : 저장소 클래스와 서비스 클래스에 대해 분리 된 인터페이스를 만들면, Repo 인터페이스에 새로운 메소드를 추가 할 때마다 서비스 인터페이스에도 추가해야합니다. 매번 두 번씩 메소드를 추가하지 않으려는 옵션이나 디자인 패턴이 있습니까? – azalut