51.16. 将正文和标头存储为文本


您可以配置 JdbcAggregationRepository 以存储消息正文,并在单独的列中选择(ed)标头作为字符串。例如,要存储正文,以下两个标头 companyNameaccountName 均使用以下 SQL:

CREATE TABLE aggregationRepo3 (
 id varchar(255) NOT NULL,
 exchange blob NOT NULL,
 version BIGINT NOT NULL,
 body varchar(1000),
 companyName varchar(1000),
 accountName varchar(1000),
 constraint aggregationRepo3_pk PRIMARY KEY (id)
);
CREATE TABLE aggregationRepo3_completed (
 id varchar(255) NOT NULL,
 exchange blob NOT NULL,
 version BIGINT NOT NULL,
 body varchar(1000),
 companyName varchar(1000),
 accountName varchar(1000),
 constraint aggregationRepo3_completed_pk PRIMARY KEY (id)
);
Copy to Clipboard Toggle word wrap

然后,配置存储库以启用此行为,如下所示:

<bean id="repo3"
  class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
  <property name="repositoryName" value="aggregationRepo3"/>
  <property name="transactionManager" ref="txManager3"/>
  <property name="dataSource" ref="dataSource3"/>
  <!-- configure to store the message body and following headers as text in the repo -->
  <property name="storeBodyAsText" value="true"/>
  <property name="headersToStoreAsText">
    <list>
      <value>companyName</value>
      <value>accountName</value>
    </list>
  </property>
</bean>
Copy to Clipboard Toggle word wrap

51.16.1. codec (Serialization)

由于它们可以包含任何类型的载荷,因此交换不可按设计序列化。它将转换为字节数组,以存储在数据库 BLOB 字段中。所有这些转换都由 JdbcCodec 类处理。代码的一个详细信息需要注意: ClassLoadingAwareObjectInputStream

ClassLoadingAwareObjectInputStream 已从 Apache ActiveMQ 项目中重复使用。它打包 ObjectInputStream,并将它与 ContextClassLoader 而不是 当前的Threader 一起使用。这样做的好处是能够加载由其他捆绑包公开的类。这允许交换正文和标头具有自定义类型对象引用。

51.16.2. 事务

需要 Spring PlatformTransactionManager 来编配事务。

51.16.2.1. 服务(Start/Stop)

start 方法验证数据库的连接以及是否存在所需的表。如果有任何错误,它将在启动过程中失败。

51.16.3. 聚合器配置

根据目标环境,聚合器可能需要进行一些配置。正如您已经了解,每个聚合器应具有自己的存储库(在数据库中创建对应的表对)和数据源。如果默认的 lobHandler 没有适应您的数据库系统,它可以使用 lobHandler 属性注入。

以下是 Oracle 的声明:

<bean id="lobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler">
  <property name="nativeJdbcExtractor" ref="nativeJdbcExtractor"/>
</bean>
<bean id="nativeJdbcExtractor"
  class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"/>
<bean id="repo"
  class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
  <property name="transactionManager" ref="transactionManager"/>
  <property name="repositoryName" value="aggregation"/>
  <property name="dataSource" ref="dataSource"/>
  <!-- Only with Oracle, else use default -->
  <property name="lobHandler" ref="lobHandler"/>
</bean>
Copy to Clipboard Toggle word wrap

51.16.4. 光驱锁定

您可以在集群环境中打开 optimisticLocking 并使用此 JDBC 的聚合存储库,其中多个 Camel 应用程序为聚合存储库共享同一数据库。如果出现 JDBC 驱动程序的竞争条件,则 JdbcAggregationRepository 可以响应特定的供应商异常。要了解 JDBC 驱动程序中的例外情况被视为 optimistick locking 错误,我们需要一个映射程序来执行此操作。因此,有 org.apache.camel.processor.aggregate.jdbc.JdbcOptimisticLockingExceptionMapper 允许您在需要时实施自定义逻辑。有默认的实现 org.apache.camel.processor.aggregate.jdbc.DefaultJdbcOptimisticLockingExceptionMapper,其工作如下:

完成以下检查:

  • 如果导致的例外是 SQLException,则如果以 23 开始,则会检查 SQLState。
  • 如果导致的例外是 DataIntegrityViolationException
  • 如果导致的异常类名称在其名称中具有 "ConstraintViolation"。
  • 如果配置了任何类名称,可选检查会匹配 FQN 类名称。

您还可以添加 FQN 类名称,如果任何导致的异常(或任何嵌套)等于任何 FQN 类名称,则它有一个 optimistick 锁定错误。

下面是一个例子,其中从 JDBC 供应商定义了 2 个额外的 FQN 类名称。

<bean id="repo"
class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
  <property name="transactionManager" ref="transactionManager"/>
  <property name="repositoryName" value="aggregation"/>
  <property name="dataSource" ref="dataSource"/>
  <property name="jdbcOptimisticLockingExceptionMapper" ref="myExceptionMapper"/>
</bean>
<!-- use the default mapper with extraFQN class names from our JDBC driver -->
<bean id="myExceptionMapper" class="org.apache.camel.processor.aggregate.jdbc.DefaultJdbcOptimisticLockingExceptionMapper">
  <property name="classNames">
    <util:set>
      <value>com.foo.sql.MyViolationExceptoion</value>
      <value>com.foo.sql.MyOtherViolationExceptoion</value>
    </util:set>
  </property>
</bean>
Copy to Clipboard Toggle word wrap

51.16.5. 传播行为

JdbcAggregationRepository 使用来自 Spring-TX 的两个不同的 事务模板。一个是只读的,一个用于读写操作。

但是,当在自己使用 < transacted /> 和使用通用平台 事务管理器的 路由中使用 JdbcAggregationRepository 时,可能需要配置 JdbcAggregationRepository 内事务模板所使用的 传播行为

以下是进行该操作的方法:

<bean id="repo"
class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
  <property name="propagationBehaviorName" value="PROPAGATION_NESTED" />
</bean>
Copy to Clipboard Toggle word wrap

传播是由 org.springframework.transaction.TransactionDefinition 接口的常量指定,因此 传播BehaviorName 是方便的设置,允许使用常量名称。

51.16.6. PostgreSQL 问题单

有特殊的数据库可能会导致 JdbcAggregationRepository 使用优化的锁定问题。如果数据完整性冲突异常(SQLState 23505)除外),PostgreSQL 会将连接标记为无效。这使得连接在嵌套事务中有效不可用。详情请参考 文档

org.apache.camel.processor.aggregate.jdbc.PostgresAggregationRepository 扩展 JdbcAggregationRepository,并使用特殊的 INSERT。ON CONFLICT .. 语句提供优化锁定行为。

此声明为 (带有默认的聚合表定义):

INSERT INTO aggregation (id, exchange) values (?, ?) ON CONFLICT DO NOTHING
Copy to Clipboard Toggle word wrap

详情请参考 PostgreSQL 文档

当使用此 子句时,java.sql.PreparedStatement.executeUpdate () 调用返回 0, 而不是抛出 SQLState=23505 的 SQLException。进一步处理与通用 JdbcAggregationRepository 相同,但没有将 PostgreSQL 连接标记为无效。

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat