当前位置: 首页 > 工具软件 > DeltaSpike > 使用案例 >

可行的DeltaSpike教程

仲浩旷
2023-12-01

在最近的项目中,我遇到了一个有趣的问题:采用被赋予一个对象的服务方法,并在一个夜进程的上下文中重用相同的代码,该夜进程将独立于应用程序运行在数千个相同类型的对象上。

试图在两个地方维护如此大小和复杂性的相同过程真是荒谬的,所以我需要找到一种共享代码的方法。 一种可能的解决方案是使用DeltaSpike (Apache的CDI扩展集合)提供一种从主要Java / JPA / Hibernate应用程序访问实体和类的简单方法。

似乎有足够的文档来使DeltaSpike在网络上以类似情况运行,但是人们对该应用程序的可行性表示怀疑。 我的团队无法让它在项目的另一部分工作,因此继续使用Spring Batch。

最大的障碍是无法创建功能性的EntityManager,无论他们如何紧密地遵循可以找到的文档和示例。 该项目的较小部分为实现DeltaSpike提供了另一个很好的候选者,但是在对以下教程非常熟悉之后,找到了操作方法,并阅读了正式的实现说明,我被困在同一个地方:EntityManager只是将无法工作,至少不能与我面前的技术和版本组合使用。

幸运的是,我能够将弗兰肯斯坦的一些教程和示例中的部分放在一起,以针对我的情况获得可行的DeltaSpike实施,因此我想我将分享我发现的内容,以便下次其他人可能会更轻松一些。

基础

首先,我正在使用Maven,因此这里是您需要添加的依赖项:

<dependency>
    <groupId>org.apache.deltaspike.cdictrl</groupId>
    <artifactId>deltaspike-cdictrl-api</artifactId>
    <version>1.2.1</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se</artifactId>
    <version>1.1.16.Final</version>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.apache.deltaspike.cdictrl</groupId>
    <artifactId>deltaspike-cdictrl-weld</artifactId>
    <version>1.2.1</version>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.apache.deltaspike.core</groupId>
    <artifactId>deltaspike-core-api</artifactId>
    <version>1.5.0</version>
</dependency>

<dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-jpa-module-api</artifactId>
    <version>1.4.0</version>
</dependency>

<dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-jpa-module-impl</artifactId>
    <version>1.4.0</version>
</dependency>

如您所见,我们正在考虑在一个也需要JBoss / Weld的项目中实现DeltaSpike。 我所依赖的其他依赖项包括javax.enterprise,Hibernate和JPA。 根据最终的实现,您可能不需要所有这些DeltaSpike依赖项,因此请确保在完成后清理pom.xml。

应用程式

对于我的示例,我将使用一个基本的Application类,该类遵循您在其他DeltaSpike示例中可能看到的模式:

import javax.enterprise.context.ApplicationScoped;
import org.apache.deltaspike.cdise.api.CdiContainer;
import org.apache.deltaspike.cdise.api.CdiContainerLoader;
import org.apache.deltaspike.cdise.api.ContextControl;
import org.apache.deltaspike.core.api.config.ConfigResolver;

public class Application {
    
    public static void main(String[] args) {
        CdiContainer cdiContainer = CdiContainerLoader.getCdiContainer();
        cdiContainer.boot();
        
        ContextControl contextControl = cdiContainer.getContextControl();
        contextControl.startContext(ApplicationScoped.class);
        
        //Your code here
        
        cdiContainer.shutdown();
    }
}

特别注意这一行:

contextControl.startContext(ApplicationScoped.class);

该行查找带有@ApplicationScoped批注的类,这些类需要包含在上下文中。

EntityManagerProducer

这是棘手的地方。 遵循典型的DeltaSpike教程,将为您提供一个类似于以下内容的EntityManagerProducer:

@ApplicationScoped
public class EntityManagerProducer
{
    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;

    @Produces
    @Default
    @RequestScoped
    public EntityManager create()
    {
        return this.entityManagerFactory.createEntityManager();
    }

    public void dispose(@Disposes @Default EntityManager entityManager)
    {
        if (entityManager.isOpen())
        {
            entityManager.close();
        }
    }
}

考虑到我要处理的各种因素,我唯一遇到的问题是根本不起作用。 无论我尝试了什么,EntityManager始终为null。 我怀疑EntityManagerFactory不能正常工作,所以我做了一些挖掘,发现这种获取EntityManagerFactory的方法:

private EntityManagerFactory entityManagerFactory = 
Persistence.createEntityManagerFactory("PERSISTENCE_UNIT", setProperties());

使用此方法,我可以基于在persistence.xml中定义的持久性单元(它具有我在参数中提供的名称)来获得一个有效的EntityManagerFactory。 在这里,我定义了应用程序需要成为EntityManagerFactory一部分的实体,以便能够执行诸如运行之类的小事情。

这是新的和改进的EntityManagerProducer的外观:

@ApplicationScoped
public class EntityManagerProducer {

    private EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("PERSISTENCE_UNIT", setProperties());

    private EntityManager entityManager;

    protected void closeEntityManager(@Disposes EntityManager entityManager) {
        if (entityManager.isOpen()) {
            entityManager.close();
        }
    }

    @Produces
    protected EntityManager createEntityManager() {
        if (entityManager == null) {
            entityManager = entityManagerFactory.createEntityManager();
        }
        return entityManager;
    }
    
    protected Properties setProperties() {
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
        properties.setProperty("hibernate.show_sql", "false");
        properties.setProperty("hibernate.hbm2ddl.auto", "none");
        properties.setProperty("hibernate.enable_lazy_load_no_trans", "true");
        properties.setProperty("hibernate.jdbc.batch_size", "20");
        properties.setProperty("hibernate.connection.driver_class", "oracle.jdbc.driver.OracleDriver");
        properties.setProperty("hibernate.connection.url", "JDBC_URL");
        properties.setProperty("hibernate.default_schema", System.getProperty("SCHEMA_NAME"));
        properties.setProperty("javax.persistence.jdbc.user", System.getProperty("USER"));
        properties.setProperty("javax.persistence.jdbc.password", System.getProperty("PASSWORD"));
        properties.setProperty("org.hibernate.flushMode", "ALWAYS");
        return properties;
    }
    
}

注意@ApplicationScoped标签; 这样可以确保在启动CDI容器时将此类包含在上下文中。 还要注意,您可以设置属性以将其传递到您创建的EntityManagerFactory中,包括从服务器参数中的系统属性中获取它们,如果环境变量可能会更改应用程序的功能,这将非常有用。

最后的想法

希望这为如何设置和实现DeltaSpike提供了一个简单有效的示例。 旁注:我最终无法使用这种方法来解决问题,因为要处理的对象数量比预期的要大得多(几百万),但是我认为分享我发现的内容仍然有用。

翻译自: https://www.javacodegeeks.com/2016/01/working-deltaspike-tutorial.html

 类似资料: