2016-02-27 64 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