2016-02-27 48 views
0

第1類:Repository.java:依賴注入和JPA和Hibernate

@ApplicationScoped 
public class Repository { 

    @Inject 
    private EntityManager em; 

    public Term findById(Long id) { 
     return em.find(Term.class, id); 
    } 
} 

二級:Word.java

@Named 
@RequestScoped 
public class Word { 

    @Inject 
    private Logger log; 

    @Inject 
    private Repository repository; 

    private Term term; 

    public Word() { 

    } 

    public Word(Long id) { 

     try{ 
      term = this.findTermById(id);  
     }catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    @Produces 
    @Named 
    public Term getTerm() { 

     return term; 
    } 

    public Term findTermById(Long id) { 

     Term term = repository.findById(id); 

     if(term==null) { 
      log.info("Can't find this word from database: " + term); 
     } 

     return term; 
    } 
} 

3類:Resources.java

public class Resources { 
    @Produces 
    @PersistenceContext 
    private EntityManager em; 

    @Produces 
    public Logger produceLog(InjectionPoint injectionPoint) { 
     return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); 
    } 

    @Produces 
    @RequestScoped 
    public FacesContext produceFacesContext() { 
     return FacesContext.getCurrentInstance(); 
    } 
} 

的這兩個類的問題是,在運行服務器時,會在該行引發NullPointerException:

Term term = repository.findById(id); 

這意味着由於調試顯示「repository = null」,所以注入對象'repository'失敗。

@Inject 
private Repository repository; 

爲什麼注射不成功?謝謝。

+1

如何獲得對Word實例的引用?異常的堆棧跟蹤是什麼? –

+3

問題出在你的'Word'構造函數中 - 你想使用依賴關係,但在構造函數中它們還沒有被注入。不要在CDI中使用構造函數,將所有邏輯從那裏移動到帶有註釋'@ PostConstruct'的方法。如果遇到任何進一步的問題(如果一個類有'@ Produces'方法需要'注入點'參數**它必須**是依賴範圍的),那麼也用'@ Dependent'註釋你的'Resource'類。 – Geinmachi

+0

@Geinmachi,問題是如何將參數「Id」傳遞給Word對象,以創建它?我可以將構造函數移動到PostConstruct方法,但何時調用此方法來執行初始化? – ling

回答

0

難道你沒有完整的stacktrace嗎?我認爲NmlPointerException可能來自private EntityManager em;在您的Repository bean中爲空。

CDI沒有看到您的類資源,因爲它沒有定義bean。 (據我可以從代碼中知道)

+0

存儲庫字段本身爲空,所以實體管理器不能存在。無論如何,它應該由'@ Produces'字段注入'Resources'類。 – Geinmachi

1

正如@Geinmachi所說,你在構造函數中調用它,但是你並沒有將它注入到構造函數中,而是在字段級別上直到@PostConstruct才被初始化。

您可以使用構造函數注入來注入存儲庫作爲參數,但是您不應該手動實例化Word,而應該通過CDI注入。因爲沒有人知道從外面的行爲,再加上你將不必在@事務會

@Inject 
public Word(Repository repo) { 
    this.repo = repo; 
} 

一般而言,構造函數不應該做的動作(如你正在做的數據庫查找),這是非常不好的做法注入。另外,您不應該手動實例化CDI bean,因爲它們的生命週期由CDI管理,並且旨在通過@Inject使用。

另外,通過擁有一個Applicationscoped實體管理器,您會遇到併發問題,它應該是requestcoped。

+0

如何做到這一點,「你可以使用構造函數注入來將庫作爲參數注入」? – ling