camel-jpa

JPA

Since Camel 1.0

Both producer and consumer are supported

JPA 组件使您能够使用 EJB 3 的 Java Persistence Architecture (JPA) 从持久存储中存储和检索 Java 对象,JPA 是一个标准接口层,它包装了对象/关系映射 (ORM) 产品,例如 OpenJPA、Hibernate、TopLink 等在。

Maven 用户需要pom.xml为此组件添加以下依赖项:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jpa</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>

发送到端点

您可以通过将 Java 实体 bean 发送到 JPA 生产者端点来将其存储在数据库中。In消息的主体被假定为实体 bean(即带有@Entity注释的 POJO )或实体 bean 的集合或数组。

如果主体是实体列表,请确保使用entityType=java.util.List作为传递给生产者端点的配置。

如果正文不包含前面列出的类型之一,请在端点前面放置一个消息转换器以首先执行必要的转换。

您也可以将query,namedQuerynativeQuery用于生产者。同样在parameters值中,您可以使用简单表达式,它允许您从消息正文、标题等中检索参数值。这些查询可用于使用SELECTJPQL/SQL 语句检索一组数据以及执行批量 update/delete 与 using UPDATE/ DELETE JPQL/SQL 语句。请注意,如果您用 namedQuery 执行UPDATE/DELETE需要指定 useExecuteUpdate 为true,与 querynativeQuery 不同,不要查看命名查询。

从端点消费

使用来自 JPA 使用者端点的消息会删除(或更新)数据库中的实体 bean。这允许您将数据库表用作逻辑队列:消费者从队列中获取消息,然后删除/更新它们以在逻辑上将它们从队列中删除。

如果您不想在处理完实体 bean 时(以及完成路由时)删除实体 bean,您可以用consumeDelete=false在 URI 上指定。这将导致在每次轮询中处理实体。

如果您更愿意对实体执行一些更新以将其标记为已处理(例如将其从未来的查询中排除),那么您可以使用@Consumed注释一个方法,当实体 bean 具有时,该方法将在您的实体 bean 上调用已处理(以及路由完成时)。

您可以使用@PreConsumed,它将在处理之前(路由之前)在您的实体 bean 上调用。

如果您消耗大量 (100K+) 行并遇到 OutOfMemory 问题,您应该将 maximumResults 设置为合理的值。

URI格式

jpa:entityClassName[?options]

为了发送到端点,entityClassName是可选的。如果指定,它有助于类型转换器确保主体的类型正确。

对于消费,entityClassName是强制性的。

配置选项

Camel 组件在两个单独的级别上配置:

  • component level

  • endpoint level

配置组件选项

组件级别是最高级别,包含端点继承的通用和通用配置。例如,组件可能具有安全设置、身份验证凭据、网络连接 url 等。

一些组件只有几个选项,而其他组件可能有很多。由于组件通常具有常用的预配置默认值,因此您可能通常只需要在组件上配置几个选项;或者根本没有。

可以使用Component DSL、在配置文件 (application.properties|yaml) 中或直接使用 Java 代码来配置组件。

配置端点选项

您发现自己配置最多的地方是在端点上,因为端点通常有很多选项,这允许您配置需要端点执行的操作。这些选项还分为端点是用作消费者(from)还是用作生产者(to),或两者都使用。

配置端点通常直接在端点 URI 中作为路径和查询参数完成。您还可以使用Endpoint DSL作为配置端点的类型安全方式。

配置选项时的一个好习惯是使用Property Placeholders,它允许不对 url、端口号、敏感信息和其他设置进行硬编码。换句话说,占位符允许从代码中外部化配置,并提供更大的灵活性和重用性。

以下两部分列出了所有选项,首先是组件,然后是端点。

组件选项

JPA 组件支持 7 个选项,如下所列。

姓名描述默认类型
entityManagerFactory(通用) 使用 EntityManagerFactory。强烈建议这样配置。   EntityManagerFactory实体管理器工厂
joinTransaction(普通) camel-jpa 组件默认会加入事务。您可以使用此选项将其关闭,例如,如果您使用 LOCAL_RESOURCE 并且连接事务不适用于您的 JPA 提供程序。此选项也可以在 JpaComponent 上全局设置,而不必在所有端点上设置。 真的 boolean
sharedEntityManager(通用) 是否为消费者/生产者使用 Spring 的 SharedEntityManager。请注意,在大多数情况下,joinTransaction 应设置为 false,因为这不是 EXTENDED EntityManager。   boolean
transactionManager (common) 使用 PlatformTransactionManager 来管理事务。   PlatformTransactionManager
bridgeErrorHandler(消费者) 允许将消费者桥接到 Camel 路由错误处理程序,这意味着在消费者尝试获取传入消息或类似消息时发生的任何异常现在都将作为消息处理并由路由错误处理程序处理。默认情况下,消费者将使用 org.apache.camel.spi.ExceptionHandler 来处理异常,这些异常将被记录在 WARN 或 ERROR 级别并被忽略。   boolean
lazyStartProducer(生产者) 生产者是否应该懒惰地启动(在第一条消息上)。通过延迟启动,您可以使用它来允许 CamelContext 和路由在生产者可能在启动过程中失败并导致路由启动失败的情况下启动。通过延迟这个启动是惰性的,启动失败可以在通过 Camel 的路由错误处理程序路由消息期间处理。请注意,当处理第一条消息时,创建和启动生产者可能需要一些时间并延长处理的总处理时间。   boolean
autowiredEnabled(高级) 是否启用自动装配。这用于自动自动装配选项(该选项必须标记为自动装配),通过在注册表中查找是否存在匹配类型的单个实例,然后在组件上进行配置。这可用于自动配置 JDBC 数据源、JMS 连接工厂、AWS 客户端等。 真的 boolean

端点选项

JPA 端点是使用 URI 语法配置的:

jpa:entityType

具有以下路径和查询参数:

路径参数(1个参数)

名称描述默认类型
entityType (common) 必需的实体类名称。   Class

查询参数(44 个参数)

姓名描述默认类型
joinTransaction(普通) camel-jpa 组件默认会加入事务。您可以使用此选项将其关闭,例如,如果您使用 LOCAL_RESOURCE 并且连接事务不适用于您的 JPA 提供程序。此选项也可以在 JpaComponent 上全局设置,而不必在所有端点上设置。 真的 boolean
maximumResults (common) 设置要在查询上检索的最大结果数。 -1 int
namedQuery (common) 使用命名查询。   String
nativeQuery(常见) 使用自定义本机查询。在使用本机查询时,您可能还想使用选项 resultClass。   String
persistenceUnit (common) 必需默认情况下使用的 JPA 持久性单元。 camel String
query (common) 使用自定义查询。   String
resultClass (common) 定义返回负载的类型(我们将调用 entityManager.createNativeQuery(nativeQuery, resultClass) 而不是 entityManager.createNativeQuery(nativeQuery))。如果没有这个选项,我们将返回一个对象数组。仅在使用数据时与本机查询结合使用时才有影响。   Class
bridgeErrorHandler(消费者) 允许将消费者桥接到 Camel 路由错误处理程序,这意味着在消费者尝试获取传入消息或类似消息时发生的任何异常现在都将作为消息处理并由路由错误处理程序处理。默认情况下,消费者将使用 org.apache.camel.spi.ExceptionHandler 来处理异常,这些异常将被记录在 WARN 或 ERROR 级别并被忽略。   boolean
consumeDelete (consumer) 如果为true,实体被消费后被删除;如果为 false,则不会删除该实体。 true boolean
consumeLockEntity (consumer) 指定在处理轮询结果时是否对每个实体 bean 设置排他锁。 true boolean
deleteHandler(消费者) 在消费者完成交换处理后使用自定义 DeleteHandler 删除行。   DeleteHandler
lockModeType(消费者) 在消费者上配置锁定模式。枚举值:读写乐观的OPTIMISTIC_FORCE_INCREMENT悲观阅读悲观写悲观_FORCE_INCREMENT没有任何 PESSIMISTIC_WRITE LockModeType
maxMessagesPerPoll(消费者) 一个整数值,用于定义每次轮询收集的最大消息数。默认情况下,没有设置最大值。可用于避免在启动服务器时轮询数千条消息。将值设置为 0 或负值以禁用。   int
preDeleteHandler(消费者) 在消费者读取实体后使用自定义 Pre-DeleteHandler 删除行。   DeleteHandler
sendEmptyMessageWhenIdle(消费者) 如果轮询使用者没有轮询任何文件,您可以启用此选项以发送空消息(无正文)。   boolean
skipLockedEntity(消费者) 配置是否在锁定时使用 NOWAIT 并静默跳过实体。   boolean
transacted (consumer) 是否在事务处理模式下运行使用者,当整个批处理完成后,所有消息将提交或回滚。默认行为 (false) 是提交所有先前成功处理的消息,并且仅回滚最后失败的消息。   boolean
exceptionHandler (consumer (advanced)) 让消费者使用自定义的 ExceptionHandler。请注意,如果选项 bridgeErrorHandler 已启用,则此选项未在使用中。默认情况下,消费者将处理异常,这些异常将记录在 WARN 或 ERROR 级别并被忽略。   ExceptionHandler
exchangePattern(消费者(高级)) 当消费者创建交换时设置交换模式。枚举值:InOnly,InOut,InOptionalOut   ExchangePattern
parameters (consumer (advanced)) 此键/值映射用于构建查询参数。它应该是泛型类型 java.util.Map,其中键是给定 JPA 查询的命名参数,值是您要为其选择的相应有效值。用于生产者时,可以使用简单表达式作为参数值。它允许您从消息正文、标题等中检索参数值。   Map
pollStrategy(消费者(高级)) 一个可插入的 org.apache.camel.PollingConsumerPollingStrategy 允许您提供自定义实现来控制在创建 Exchange 并在 Camel 中路由之前轮询操作期间通常发生的错误处理。   PollingConsumerPollStrategy
findEntity(生产者) 如果启用,那么生产者将使用消息正文作为键和 entityType 作为类型来查找单个实体类。这可以用来代替查询来查找单个实体。   boolean
flushOnSend(生产者) 在实体 bean 被持久化后刷新 EntityManager。 true boolean
lazyStartProducer(生产者) 生产者是否应该懒惰地启动(在第一条消息上)。通过延迟启动,您可以使用它来允许 CamelContext 和路由在生产者可能在启动过程中失败并导致路由启动失败的情况下启动。通过延迟这个启动是惰性的,启动失败可以在通过 Camel 的路由错误处理程序路由消息期间处理。请注意,当处理第一条消息时,创建和启动生产者可能需要一些时间并延长处理的总处理时间。   boolean
remove (producer) 表示使用 entityManager.remove(entity)。   boolean
useExecuteUpdate(生产者) 配置生产者执行查询时是否使用executeUpdate()。当您使用 INSERT、UPDATE 或 DELETE 语句作为命名查询时,您需要将此选项指定为 'true'。   boolean
usePersist(生产者) 表示使用 entityManager.persist(entity) 而不是 entityManager.merge(entity)。注意:entityManager.persist(entity) 不适用于分离的实体(其中 EntityManager 必须执行 UPDATE 而不是 INSERT 查询)!。   boolean
usePassedInEntityManager(生产者(高级)) 如果设置为 true,则 Camel 将使用头文件 JpaConstants.ENTITY_MANAGER 中的 EntityManager 而不是组件/端点上配置的实体管理器。这允许最终用户控制将使用哪个实体管理器。   boolean
entityManagerProperties(高级) 实体管理器使用的附加属性。   map
sharedEntityManager(高级) 是否为消费者/生产者使用 Spring 的 SharedEntityManager。请注意,在大多数情况下,joinTransaction 应设置为 false,因为这不是 EXTENDED EntityManager。   boolean
backoffErrorThreshold(调度程序) 在 backoffMultipler 启动之前应该发生的后续错误轮询(由于某些错误而失败)的数量。   int
backoffIdleThreshold(调度程序) 在 backoffMultipler 应该启动之前应该发生的后续空闲轮询的数量。   int
backoffMultiplier(调度程序) 如果连续出现许多后续空闲/错误,则让计划的轮询使用者退避。乘数是在下一次实际尝试再次发生之前将被跳过的轮询次数。使用此选项时,还必须配置 backoffIdleThreshold 和/或 backoffErrorThreshold。   int
delay (scheduler) 下一次轮询前的毫秒数。 500 long
greedy (scheduler) 如果启用了贪婪,则 ScheduledPollConsumer 将立即再次运行,如果前一次运行轮询了 1 条或多条消息。   boolean
initialDelay (scheduler) 第一次轮询开始前的毫秒数。 1000 long
repeatCount (scheduler) 指定火灾次数的最大限制。因此,如果将其设置为 1,调度程序将只触发一次。如果将其设置为 5,则它只会触发 5 次。零或负值意味着永远燃烧。   long
runLoggingLevel(调度程序) 消费者在轮询时记录开始/完成日志行。此选项允许您为此配置日志记录级别。枚举值:痕迹调试信息警告错误离开 TRACE LoggingLevel
ScheduledExecutorService(调度程序) 允许配置自定义/共享线程池以供使用者使用。默认情况下,每个使用者都有自己的单线程线程池。   ScheduledExecutorServiceScheduledExecutorService
scheduler (scheduler) 使用来自camel-spring 或camel-quartz 组件的cron 调度程序。对内置调度器使用值弹簧或石英。 none Object
schedulerProperties(调度程序) 在使用自定义调度程序或任何基于 Quartz、Spring 的调度程序时配置其他属性。   map
startScheduler(调度程序) 调度程序是否应该自动启动。 true boolean
timeUnit (scheduler) initialDelay 和延迟选项的时间单位。枚举值:纳秒微秒毫秒秒分钟小时天 MILLISECONDS TimeUnit
useFixedDelay(调度程序) 控制是否使用固定延迟或固定速率。有关详细信息,请参阅 JDK 中的 ScheduledExecutorService。 true boolean

消息头

Camel 将以下消息头添加到交换中:

标题类型描述
CamelEntityManager EntityManager EntityManager正在使用的 JPA对象。JpaConsumer``JpaProducer
CamelJpaParameters Map<String, Object> 将查询参数作为 Exchange 标头传递的替代方法。

配置 ENTITYMANAGERFACTORY

强烈建议配置 JPA 组件以使用特定EntityManagerFactory实例。如果不这样做,每个人JpaEndpoint都会自动创建自己的实例,EntityManagerFactory而这些实例通常不是您想要的。

例如,您可以实例化一个引用myEMFactory实体管理器工厂的 JPA 组件,如下所示:

<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
   <property name="entityManagerFactory" ref="myEMFactory"/>
</bean>

JpaComponent查找自动EntityManagerFactory从,这意味着你不需要在配置此注册表JpaComponent如上图所示。只有在有歧义时才需要这样做,在这种情况下,Camel 会记录一个 WARN。

配置事务管理器

JpaComponent自动查找TransactionManager从注册表。如果 Camel 找不到任何TransactionManager已注册的实例,它也会查找TransactionTemplate并尝试从中提取TransactionManager

如果TransactionTemplate注册表中没有可用的,JpaEndpoint将自动创建自己的实例,TransactionManager其中最常见的不是您想要的。

如果找到多个 的实例TransactionManager,Camel 将记录一个 WARN。在这种情况下,您可能希望实例化并显式配置引用myTransactionManager事务管理器的 JPA 组件,如下所示:

<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
   <property name="entityManagerFactory" ref="myEMFactory"/>
   <property name="transactionManager" ref="myTransactionManager"/>
</bean>

使用带有命名查询的消费者

对于仅使用选定实体,您可以使用namedQueryURI 查询选项。首先,您必须在 JPA 实体类中定义命名查询:

@Entity
@NamedQuery(name = "step1", query = "select x from MultiSteps x where x.step = 1")
public class MultiSteps {
   ...
}

之后,您可以像这样定义一个消费者 uri:

from("jpa://org.apache.camel.examples.MultiSteps?namedQuery=step1")
.to("bean:myBusinessLogic");

使用消费者进行查询

对于仅使用选定实体,您可以使用queryURI 查询选项。您只需要定义查询选项:

from("jpa://org.apache.camel.examples.MultiSteps?query=select o from org.apache.camel.examples.MultiSteps o where o.step = 1")
.to("bean:myBusinessLogic");

使用带有本机查询的使用者

对于仅使用选定实体,您可以使用nativeQueryURI 查询选项。您只需要定义本机查询选项:

from("jpa://org.apache.camel.examples.MultiSteps?nativeQuery=select * from MultiSteps where step = 1")
.to("bean:myBusinessLogic");

如果您使用本机查询选项,您将在消息正文中收到一个对象数组。

使用带有命名查询的生产者

要检索选定的实体或执行批量更新/删除,您可以使用namedQueryURI 查询选项。首先,您必须在 JPA 实体类中定义命名查询:

@Entity
@NamedQuery(name = "step1", query = "select x from MultiSteps x where x.step = 1")
public class MultiSteps {
   ...
}

之后,您可以像这样定义一个生产者 uri:

from("direct:namedQuery")
.to("jpa://org.apache.camel.examples.MultiSteps?namedQuery=step1");

请注意,您需要指定useExecuteUpdate选项以trueUPDATE/DELETE语句作为命名查询执行。

使用带有查询的生产者

要检索选定的实体或执行批量更新/删除,您可以使用queryURI 查询选项。您只需要定义查询选项:

from("direct:query")
.to("jpa://org.apache.camel.examples.MultiSteps?query=select o from org.apache.camel.examples.MultiSteps o where o.step = 1");

使用带有本机查询的生产者

要检索选定的实体或执行批量更新/删除,您可以使用nativeQueryURI 查询选项。您只需要定义本机查询选项:

from("direct:nativeQuery")
.to("jpa://org.apache.camel.examples.MultiSteps?resultClass=org.apache.camel.examples.MultiSteps&nativeQuery=select * from MultiSteps where step = 1");

如果您使用本机查询选项而不指定resultClass,您将在消息正文中收到一个对象数组。

使用基于 JPA 的幂等存储库

EIP 模式中的幂等消费者用于过滤掉重复的消息。提供了一个基于 JPA 的幂等存储库。

使用基于 JPA 的幂等存储库。

程序

  1. persistence-unit在persistence.xml文件中设置一个:

  2. 设置一个org.springframework.orm.jpa.JpaTemplate由以下使用的org.apache.camel.processor.idempotent.jpa.JpaMessageIdRepository

  3. 配置错误格式宏:snippet: java.lang.IndexOutOfBoundsException: Index: 20, Size: 20

  4. 配置幂等存储库org.apache.camel.processor.idempotent.jpa.JpaMessageIdRepository

  5. 在 Spring XML 文件中创建 JPA 幂等存储库:

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route id="JpaMessageIdRepositoryTest">
        <from uri="direct:start" />
        <idempotentConsumer messageIdRepositoryRef="jpaStore">
            <header>messageId</header>
            <to uri="mock:result" />
        </idempotentConsumer>
    </route>
</camelContext>

在 IDE 中运行此 Camel 组件测试时

如果您直接在 IDE 中运行此组件测试,而不是通过 Maven,那么您可能会看到如下异常:

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is
<openjpa-2.2.1-r422266:1396819 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: This configuration disallows runtime optimization,
but the following listed types were not enhanced at build time or at class load time with a javaagent: "org.apache.camel.examples.SendEmail".
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:427)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:127)
    at org.apache.camel.processor.jpa.JpaRouteTest.cleanupRepository(JpaRouteTest.java:96)
    at org.apache.camel.processor.jpa.JpaRouteTest.createCamelContext(JpaRouteTest.java:67)
    at org.apache.camel.test.junit5.CamelTestSupport.doSetUp(CamelTestSupport.java:238)
    at org.apache.camel.test.junit5.CamelTestSupport.setUp(CamelTestSupport.java:208)

这里的问题是源代码是通过您的 IDE 而不是通过 Maven 编译或重新编译的,这会在构建时增强字节码。为了克服这个问题,您需要启用OpenJPA 的动态字节码增强。例如,假设 Camel 中使用的当前 OpenJPA 版本是 2.2.1,要在您的 IDE 中运行测试,您需要将以下参数传递给 JVM:

-javaagent:<path_to_your_local_m2_cache>/org/apache/openjpa/openjpa/2.2.1/openjpa-2.2.1.jar

SPRING BOOT 自动配置

在 Spring Boot 中使用 jpa 时,请确保使用以下 Maven 依赖项来支持自动配置:

<dependency>
  <groupId>org.apache.camel.springboot</groupId>
  <artifactId>camel-jpa-starter</artifactId>
  <version>x.x.x</version>
  <!-- use the same version as your Camel core version -->
</dependency>

该组件支持 8 个选项,如下所列。

姓名描述默认类型
camel.component.jpa.autowired-enabled 是否启用自动装配。这用于自动自动装配选项(该选项必须标记为自动装配),通过在注册表中查找是否存在匹配类型的单个实例,然后在组件上进行配置。这可用于自动配置 JDBC 数据源、JMS 连接工厂、AWS 客户端等。 true Boolean
camel.component.jpa.bridge-error-handler 允许将消费者桥接到 Camel 路由错误处理程序,这意味着在消费者尝试获取传入消息或类似消息时发生的任何异常现在都将作为消息处理并由路由错误处理程序处理。默认情况下,消费者将使用 org.apache.camel.spi.ExceptionHandler 来处理异常,这些异常将被记录在 WARN 或 ERROR 级别并被忽略。 false Boolean
camel.component.jpa.enabled 是否启用 jpa 组件的自动配置。这是默认启用的。   Boolean
camel.component.jpa.entity-manager-factory 使用 EntityManagerFactory。强烈建议这样配置。该选项是 javax.persistence.EntityManagerFactory 类型。   EntityManagerFactory
camel.component.jpa.join-transaction camel-jpa 组件默认会加入事务。您可以使用此选项将其关闭,例如,如果您使用 LOCAL_RESOURCE 并且连接事务不适用于您的 JPA 提供程序。此选项也可以在 JpaComponent 上全局设置,而不必在所有端点上设置。 true Boolean
camel.component.jpa.lazy-start-producer 生产者是否应该懒惰地启动(在第一条消息上)。通过延迟启动,您可以使用它来允许 CamelContext 和路由在生产者可能在启动过程中失败并导致路由启动失败的情况下启动。通过延迟这个启动是惰性的,启动失败可以在通过 Camel 的路由错误处理程序路由消息期间处理。请注意,当处理第一条消息时,创建和启动生产者可能需要一些时间并延长处理的总处理时间。 false Boolean
camel.component.jpa.shared-entity-manager 是否为消费者/生产者使用 Spring 的 SharedEntityManager。请注意,在大多数情况下,joinTransaction 应设置为 false,因为这不是 EXTENDED EntityManager。 false Boolean
camel.component.jpa.transaction-manager 使用 PlatformTransactionManager 来管理事务。该选项是 org.springframework.transaction.PlatformTransactionManager 类型。   PlatformTransactionManager
posted @ 2021-09-30 14:12  yiwenzhang  阅读(502)  评论(0编辑  收藏  举报