2014-07-21 66 views
1

我的spring應用程序沒有問題。這裏是我的代碼:Spring annotations:@Component works,@Repository does not

(庫)

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); 
    } 
} 

和簡單的測試類:

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()); 
    } 
} 

的問題是,當我註釋EtwasHibernateRepository@Component,一切工作正常。當我添加,實際上是 - @Repository註釋我得到一個堆棧跟蹤: 你有anny建議我做錯了什麼?

PS 的代碼是非常簡單的,捲入並提出只是爲了測試,所以不要有關:)

異常線程「main」 org.springframework.beans.factory.BeanCreationException護理:錯誤 創建名爲'etwasService'的bean:注入自動裝配的 依賴關係失敗;嵌套的例外是 org.springframework.beans.factory.BeanCreationException:無法 自動裝配領域:私人 com.maciej.repository.impl.EtwasHibernateRepository com.maciej.services.EtwasService.etwasHibernateRepository;嵌套0​​例外是 org.springframework.beans.factory.NoSuchBeanDefinitionException:否 [com.maciej.repository.impl.EtwasHibernateRepository]類型的 排位豆找到 依賴性:預期至少1豆,其有資格作爲自動裝配 候選這種依賴性。依賴註解: {@ org.springframework.beans.factory.annotation.Autowired(所需=真)} 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292) 在 有機.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) 在 org.springframework.beans .factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) at org.springframework.beans.factory.support.AbstractBeanFactory $ 1.getObject(AbstractBeanFactory.java:304) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 在 組織。 springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) 在 org.springframework.beans。 factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703) at org.springframework.context.support.AbstractApplicationContext.finishBea nFactoryInitialization(AbstractApplicationContext.java:760) at org。(Test。)。在測試環境中,您可以使用以下代碼來創建測試代碼:Test.ConfigApplicationContext.java:84,。的java:12)在 sun.reflect.NativeMethodAccessorImpl.invoke0(本機方法)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(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: 無法自動裝入字段:private com.maciej.repository.impl.EtwasHibernateRepository com.maciej.services.EtwasService.etwasHibernateRepository;嵌套0​​例外是 org.springframework.beans.factory.NoSuchBeanDefinitionException:否 [com.maciej.repository.impl.EtwasHibernateRepository]類型的 排位豆找到 依賴性:預期至少1豆,其有資格作爲自動裝配 候選這種依賴性。依賴註釋: {@ org.springframework.beans.factory.annotation.Autowired(必需=真)} 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508) 在 org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ... 17個造成者: org.springframework.beans.factory.NoSuchBeanDefinitionException:否 符合條件的bean類型 [com.maciej.r epository.impl.EtwasHibernateRepository]找到 依賴關係:預計至少有1個bean符合自動連線 候選此依賴關係。依賴註解: 在 有機{@ org.springframework.beans.factory.annotation.Autowired(所需=真)} 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103) .springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858) 在 org.springframework.beans .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; 

的自動裝配依賴是全面實現類的,而應該是EtwasRepository。這將使其適用於@Component@Repository。除此之外,這也是正確的做法。

@Service 
@Transactional 
public class EtwasService { 

    @Autowired 
    private EtwasRepository etwasHibernateRepository; 

豆類與@Repository註釋將啓用自動異常翻譯,這施加AOP。默認情況下,Spring使用基於接口的JDK動態代理。它將創建一個實現EtwasRepository界面的動態類並應用aop攔截器。這使得豆類EtwasRepository,而不是EtwasHibernateRepository類型。

註釋您的豆@Component時不應用此轉換。

關於您的配置的說明不需要明確聲明PersistenceExceptionTranslationPostProcessor。這已經被處理了。

+0

所以現在我想問幾個問題:1.關於@Service?我現在沒有實現接口的服務類,@Service服務於它。 2.我在春天和jpa很新,實際上不知道:異常翻譯是做什麼的? 3.我應該爲服務和存儲庫以及「帶接口的代碼」創建接口嗎? – azalut

+0

'@ Service'目前沒有應用其他行爲。你的'@ Transactional'的確如此,但是由於你沒有實現一個接口,所以會創建一個cglib代理(基於類)。一般來說,我喜歡通過類的接口,但與許多事情一樣,要求10個開發人員並獲得12個答案:)。 –

+0

是的,但我想知道接口編程中的一件事情:讓我們看看Spring MVC,有@Controllers @ Services和@ Repositories。 @ Controller應該調用@ Service,然後@ Service應該調用@ Repository。所以:如果我爲存儲庫類和服務類創建分離的接口,那麼每次我想向repo接口添加新方法時,我也必須將它添加到服務接口中。有沒有任何選擇或設計模式,以避免每次添加方法兩次? – azalut

相關問題