【问题标题】:Dependency Injection and JPA and Hibernate依赖注入和 JPA 和 Hibernate
【发布时间】:2016-02-27 00:22:12
【问题描述】:

第 1 类:Repository.java:

@ApplicationScoped
public class Repository {

    @Inject
    private EntityManager em;

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

第 2 类: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”失败,因为调试显示“repository=null”。

@Inject
private Repository repository;

为什么注入不成功?谢谢。

【问题讨论】:

  • 如何获得对 Word 实例的引用?异常的堆栈跟踪是什么?
  • 问题出在你的Word 构造函数中——你想使用依赖,但是在构造函数中它们还没有被注入。不要在 CDI 中使用构造函数,将所有逻辑从那里移到带有注释 @PostConstruct 的方法中。如果您遇到任何进一步的问题,还要用@Dependent 注释您的Resource 类(如果一个类具有采用InjectionPoint 参数的@Produces 方法,它必须 是依赖范围)。
  • @Geinmachi,问题是如何将参数“Id”传递给 Word 对象,以便创建它?我可以将构造函数移动到 PostConstruct 方法,但是什么时候调用这个方法进行初始化?
  • 这是另一个问题。您不应该通过new 创建托管 bean。如果你这样做(我猜你是通过使用带参数的构造函数来做到的),那么它不会由容器管理,并且不会注入任何东西(生命周期也失败)。你应该说明你在哪里使用这个构造函数,也许可以考虑使用@Produces 方法。
  • 我明白了。谢谢你。我会改变设计。

标签: hibernate jpa dependency-injection jboss cdi


【解决方案1】:

正如@Geinmachi 所说,您在构造函数中调用它,但不是在构造函数中注入它,而是在字段级别注入,直到@PostConstruct 才初始化。

您可以使用构造函数注入将存储库作为参数注入,但您不应手动实例化 Word,而应通过 CDI 注入。

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

一般来说,构造函数永远不应该执行操作(例如您正在执行的数据库查找),这是非常糟糕的做法,因为没有人知道外部的行为,而且您在 @Inject 期间不会进行事务。此外,您不应手动实例化 CDI bean,因为它们的生命周期由 CDI 管理,并且旨在通过 @Inject 使用。

另外,如果你有一个 Applicationscoped entitymanager,你也会遇到并发问题,它应该是 requestscoped。

【讨论】:

  • 怎么做,“您可以使用构造函数注入将存储库作为参数注入”?
【解决方案2】:

您没有完整的堆栈跟踪吗?我认为 NullPointerException 可能来自 private EntityManager em; 在您的 Repository bean 中为 null。

CDI 看不到您的资源类,因为它没有定义 bean。 (据我从代码中可以看出。)

【讨论】:

  • Repository 字段本身为空,因此实体管理器不能在那里。无论如何,它应该由Resources 类中的@Produces 字段注入。
猜你喜欢
  • 2011-02-12
  • 2018-08-11
  • 2021-11-19
  • 1970-01-01
  • 2017-04-02
  • 2012-02-15
  • 2011-05-11
  • 2011-04-04
  • 2017-03-25
相关资源
最近更新 更多