在 Java SE 中拥有 CDI 和 JPA 的最简单方法是啥?

Posted

技术标签:

【中文标题】在 Java SE 中拥有 CDI 和 JPA 的最简单方法是啥?【英文标题】:What is the easiest way to have CDI and JPA in Java SE?在 Java SE 中拥有 CDI 和 JPA 的最简单方法是什么? 【发布时间】:2014-01-23 00:44:51 【问题描述】:

我想在 Java SE 中拥有

@Stateless
public class CarDAO 
    @Inject
    private EntityManager em;

    public Car findById(Long id) 
        return em.find(Car.class, id);
    


@Singleton
public class Application 
    @Inject
    private CarDAO carDAO;

    public void run() 
        Car car = carDAO.findById(44);
        System.out.println(car);
    


public class EntryPoint 
    public static void main(String[] args) 
        Application application = // missing code
        application.run();
    

我必须做些什么来实现这一目标?我在我的项目中使用 postgres 数据库和 maven。

我已经在阅读有关 Weld 的文章(但它看起来只是 CDI)。我不知道如何添加到 Weld 注入实体管理器的可能性。我知道我可以通过

获得Entity Manager
EntityManagerFactory emf = Persistence.createEntityManagerFactory("mgr");
EntityManager em = emf.createEntityManager();

但没有注入那么方便。

如果有这方面的教程就好了。无论如何,感谢您的帮助!

【问题讨论】:

您使用的是什么 CDI 容器?什么版本?最常见的模式是在实例化 EMF 后为实体管理器使用生产者。 【参考方案1】:

首先,EJB 是 Java EE 的一部分,因此您不能在 Java SE 中使用它们。但是,CDI 可以在 Java SE 环境中使用,我的示例将向您展示如何将它与 Weld 一起使用,但还有其他实现 - 请注意,CDI 只是规范,而 Weld 是该规范的实现之一。

要使用 Weld,您需要将 weld-se-x.x.x-Final.jar 放在类路径中,或者在 Maven 中指定其依赖项,如

<dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se</artifactId>
    <version><!-- See https://mvnrepository.com/artifact/org.jboss.weld.se/weld-se for current version --></version>
</dependency>

然后你需要在你的main方法中启动容器,所以做这样的事情

public static void main(String[] args) throws IOException 
    Weld weld = new Weld();
    WeldContainer container = weld.initialize();
    Application application = container.instance().select(Application.class).get();
    application.run();
    weld.shutdown();

这应该可以帮助您入门,然后您可以使用 CDI Producers 使您的 EntityManager 可注入

@Produces
@RequestScoped
public EntityManager createEntityManager() 
   return Persistence.createEntityManagerFactory("mgr").createEntityManager();


public void closeEM(@Disposes EntityManager manager) 
   manager.close();

另见Weld documentation on using CDI in Java SE。

【讨论】:

您的解决方案有效。你现在能告诉我,我是否必须在 EntityManager 和/或 EntityManagerFactory 上的某个地方打电话 close() 最简单的是 disposer 方法,这将在 EntityManager 的范围到期后自动关闭 - 请参阅我的编辑。 为什么要使用@EntityManager 限定符? 对不起,根据文档,你似乎不需要限定符,试试看 docs.jboss.org/cdi/spec/1.1/…【参考方案2】:

Peter 的回答似乎有效,但 Maven 依赖项已过时(请参阅 this bug)

<dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se-core</artifactId>
    <version>2.3.1.Final</version>
</dependency>
<dependency>
    <groupId>org.jboss.weld</groupId>
    <artifactId>weld-core</artifactId>
    <version>2.3.1.Final</version>
</dependency>
<dependency>
    <groupId>org.jboss</groupId>
    <artifactId>jandex</artifactId>
    <version>1.2.2.Final</version>
</dependency>

【讨论】:

以上是关于在 Java SE 中拥有 CDI 和 JPA 的最简单方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

CDI + JPA 多个 @OneToMany - LAZY/EAGER - LazyInitializationException 或无法实例化多个包

Spring 会支持 CDI 吗? [关闭]

CDI 中的 Spring-JDBC 等价物是啥?

Java SE环境中测试JPA实体的简单方法

Java SE 上的 JPA:对象:entity.Customer@5e80188f 不是已知的实体类型

如何在 CDI 环境中管理 EntityManager 生命周期(使用 Tomcat)