JDBC
Since Camel 1.2
仅支持生产者
JDBC 组件使您能够通过 JDBC 访问数据库,其中 SQL 查询 (SELECT) 和操作(INSERT、UPDATE 等)在消息正文中发送。该组件使用标准的 JDBC API,与SQL 组件组件不同,它使用 spring-jdbc。
笔记 | 当你使用Spring和需要支持Spring的事务时,使用Spring JDBC组件,代替这个组件。 |
---|
Maven 用户需要pom.xml
为此组件添加以下依赖项:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jdbc</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency>
此组件只能用于定义生产者端点,这意味着您不能在from()
语句中使用 JDBC 组件。
URI格式
jdbc:dataSourceName[?options]
配置选项
Camel 组件在两个单独的级别上配置:
-
component level
-
endpoint level
组件级别是*别,包含端点继承的一般的和通用配置。例如,组件可能具有安全设置、身份验证凭据、网络连接 url 等。
一些组件只有几个选项,而其他组件可能有很多。由于组件通常具有常用的预配置默认值,因此您可能通常只需要在组件上配置几个选项;或者根本没有。
可以使用Component DSL、在配置文件 (application.properties|yaml) 中或直接使用 Java 代码来配置组件。
配置ENDPOINT选项
您发现自己配置最多的地方是在端点上,因为端点通常有很多选项,这允许您配置需要端点执行的操作。这些选项还分为端点是用作消费者(from)还是用作生产者(to),或者两者都使用。
配置端点通常直接在端点 URI 中作为路径和查询参数完成。您还可以使用Endpoint DSL作为配置端点的类型安全方式。
配置选项时的一个好习惯是使用Property Placeholders,它允许不对 url、端口号、敏感信息和其他设置进行硬编码。换句话说,占位符允许从代码中外部化配置,并提供更大的灵活性和重用性。
以下两部分列出了所有选项,首先是组件,然后是端点。
组件选项
JDBC 组件支持 4 个选项,如下所列。
名称 | 描述 | 默认 | 类型 |
---|---|---|---|
dataSource (producer) | 使用 DataSource 实例而不是从注册表中按名称查找数据源。 | DataSource | |
lazyStartProducer(producer) | 生产者是否应该懒惰地启动(在第一条消息上)。通过延迟启动,您可以使用它来允许 CamelContext 和路由在生产者可能在启动过程中失败并导致路由启动失败的情况下启动。通过延迟启动,启动失败可以在通过 Camel 的路由错误处理程序路由消息期间处理。请注意,当处理第一条消息时,创建和启动生产者可能需要一些时间并延长处理的总处理时间。 | boolean | |
autowiredEnabled(advanced) | 是否启用自动装配。这用于自动装配选项(该选项必须标记为自动装配),通过在注册表中查找是否存在匹配类型的单个实例,然后在组件上进行配置。这可用于自动配置 JDBC 数据源、JMS 连接工厂、AWS 客户端等。 | 真的 | boolean |
connectionStrategy(advanced) | 使用自定义策略处理连接。使用 spring-jdbc 组件时不要使用自定义策略,因为默认情况下使用特殊的 Spring ConnectionStrategy 来支持 Spring Transactions。 | ConnectionStrategy |
端点选项
JDBC 端点是使用 URI 语法配置的:
jdbc:dataSourceName
具有以下路径和查询参数:
路径参数(1个参数)
姓名 | 描述 | 默认 | 类型 |
---|---|---|---|
dataSourceName (producer) | 要在注册表中查找的数据源的必需名称。如果名称是 dataSource 或 default,则 Camel 将尝试从注册表中查找默认 DataSource,这意味着如果只找到一个 DataSource 实例,则将使用此 DataSource。 | string |
查询参数(14个参数)
姓名 | 描述 | 默认 | 类型 |
---|---|---|---|
allowNamedParameters(生产者) | 是否允许在查询中使用命名参数。 | true | 布尔值 |
lazyStartProducer(生产者) | 生产者是否应该懒惰地启动(在第一条消息上)。通过延迟启动,您可以使用它来允许 CamelContext 和路由在生产者可能在启动过程中失败并导致路由启动失败的情况下启动。通过延迟启动,启动失败可以在通过 Camel 的路由错误处理程序路由消息期间处理。请注意,当处理第一条消息时,创建和启动生产者可能需要一些时间并延长处理的总处理时间。 | 布尔值 | |
outputClass (producer) | 指定在 outputType=SelectOne 或 SelectList 时用作转换的完整包和类名。 | 细绳 | |
outputType (producer) | 确定生产者应该使用的输出。枚举值:选择一个选择列表流列表 | 选择列表 | JDBC输出类型 |
parameters (producer) | java.sql.Statement 的可选参数。例如设置 maxRows、fetchSize 等。 | 地图 | |
readSize (producer) | 轮询查询可以读取的默认最大行数。默认值为 0。 | 整数 | |
resetAutoCommit(生产者) | Camel 会将 JDBC 连接上的 autoCommit 设置为 false,如果 resetAutoCommit 为 true,则在执行该语句后提交更改并在最后重置连接的 autoCommit 标志。如果 JDBC 连接不支持重置 autoCommit 标志,您可以将 resetAutoCommit 标志设置为 false,Camel 不会尝试重置 autoCommit 标志。当与 XA 事务一起使用时,您很可能需要将其设置为 false,以便事务管理器负责提交此 tx。 | true | 布尔值 |
transacted (producer) | 是否正在使用事务。 | 布尔值 | |
useGetBytesForBlob(生产者) | 将 BLOB 列作为字节而不是字符串数据读取。对于某些数据库(例如 Oracle),您必须将 BLOB 列作为字节读取,这可能是必需的。 | 布尔值 | |
useHeadersAsParameters(生产者) | 将此选项设置为 true 以使用带有命名参数的 prepareStatementStrategy。这允许使用命名占位符定义查询,并使用带有查询占位符动态值的标题。 | 布尔值 | |
useJDBC4ColumnNameAndLabelSemantics(生产者) | 设置检索列名时是使用 JDBC 4 还是 JDBC 3.0 或更旧的语义。JDBC 4.0 使用 columnLabel 来获取列名,而 JDBC 3.0 使用 columnName 或 columnLabel。不幸的是,JDBC 驱动程序的行为有所不同,因此如果您在使用此组件时遇到问题,您可以使用此选项来解决有关 JDBC 驱动程序的问题。此选项默认为 true。 | true | 布尔值 |
beanRowMapper(高级) | 在使用 outputClass 时使用自定义 org.apache.camel.component.jdbc.BeanRowMapper。默认实现将小写行名称并跳过下划线和破折号。例如,CUST_ID 被映射为 custId。 | BeanRowMapper | |
connectionStrategy (advanced) | 使用自定义策略处理连接。使用 spring-jdbc 组件时不要使用自定义策略,因为默认情况下使用特殊的 Spring ConnectionStrategy 来支持 Spring Transactions。 | 连接策略 | |
prepareStatementStrategy(高级) | 允许插件使用自定义 org.apache.camel.component.jdbc.JdbcPrepareStatementStrategy 来控制查询和准备语句的准备。 | JdbcPrepareStatement策略 |
结果
默认情况下,结果在 OUT 正文中作为ArrayList<HashMap<String, Object>>
. 该List
对象包含行的列表和Map
对象包含每一行与String
键的列名。您可以使用该选项outputType
来控制结果。
注意:该组件获取ResultSetMetaData
能够返回列名作为Map
.
消息头
标题 | 描述 |
---|---|
CamelJdbcRowCount |
如果查询是SELECT ,则查询在此 OUT 标头中返回行计数。 |
CamelJdbcUpdateCount |
如果查询是UPDATE ,则查询更新计数在此 OUT 标头中返回。 |
CamelGeneratedKeysRows |
包含生成的键的行。 |
CamelGeneratedKeysRowCount |
标题中包含生成的键的行数。 |
CamelJdbcColumnNames |
ResultSet 中的列名称作为java.util.Set 类型。 |
CamelJdbcParameters |
一个java.util.Map 如果要使用具有头useHeadersAsParameters 已启用。 |
生成主键
如果您使用 SQL INSERT 插入数据,则 RDBMS 可能支持自动生成的键。您可以指示JDBC生产者在标头中返回生成的键。 为此,请设置 header CamelRetrieveGeneratedKeys=true
。然后生成的密钥将作为标头提供,其中包含上表中列出的密钥。
使用生成的键不能与命名参数一起使用。
使用命名参数
在下面给定的路线中,我们希望从项目表中获取所有项目。注意 SQL 查询有 2 个命名参数,:?lic 和 :?min。 Camel 然后会从消息头中查找这些参数。请注意,在上面的示例中,我们为命名参数设置了两个具有常量值的标头:
from("direct:projects") .setHeader("lic", constant("ASF")) .setHeader("min", constant(123)) .setBody("select * from projects where license = :?lic and id > :?min order by id") .to("jdbc:myDataSource?useHeadersAsParameters=true")
您还可以将标头值存储在 java.util.Map
中,并使用键将映射存储在标头上CamelJdbcParameters
。
示例
在以下示例中,我们从客户表中获取行。
首先,我们在 Camel 注册表中将我们的数据源注册为testdb
:
然后我们配置一个路由到JDBC组件的路由,这样SQL就会被执行。请注意我们如何引用testdb
在上一步中绑定的数据源:
或者你可以DataSource
像这样在 Spring 中创建一个:
使用 spring xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd"> <!-- PROPERTY PLACEHOLDERS --> <!-- You may use property placeholders data store configuration for to do that, you can resolve this properties with srping --> <bean id="db" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"> <property name="location" value="classpath:db.properties"/> </bean> <!-- DATA STORE CONFIGURATION --> <!-- In this example the DataStore is a postgres database, you can change the jdbc connector. Also, the property testWhileIdle and validationQuery keep connection open. --> <bean id="DataStore" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.postgresql.Driver" /> <property name="url" value="jdbc:postgresql://${DB_HOST}/${DB_NAME}"/> <property name="username" value="${DB_USER}" /> <property name="password" value="${DB_PASS}" /> <property name="initialSize" value="4"/> <property name="maxActive" value="15"/> <property name="maxIdle" value="16"/> <property name="minIdle" value="8"/> <property name="timeBetweenEvictionRunsMillis" value="1800"/> <property name="minEvictableIdleTimeMillis" value="1800"/> <property name="testOnBorrow" value="true"/> <property name="testWhileIdle" value="true"/> <property name="testOnReturn" value="true"/> <property name="validationQuery" value="SELECT 1"/> <property name="maxWait" value="1000"/> <property name="removeAbandoned" value="true"/> <property name="logAbandoned" value="true"/> <property name="removeAbandonedTimeout" value="30000"/> </bean> <!-- You shuould write a file with an script to initialize your database. If you have nothing to do with your database, then you can write just a validation query like 'SELECT *; '--> <jdbc:initialize-database data-source="DataStore" enabled="true"> <jdbc:script location="classpath:datastore-schema.sql" /> </jdbc:initialize-database> <camelContext xmlns="http://camel.apache.org/schema/spring"> <!-- CAMEL ROUTE --> <route id="Reporter"> <from uri="direct:to-datastore"/> <!-- this example is done with camel-jdbc but you can make it work with camel-sql --> <setBody> <simple>insert into test '${body[value]}'</simple> </setBody> <to uri="jdbc:DataStore"/> </route> </camelContext>
我们创建一个端点,将 SQL 查询添加到 IN 消息的正文中,然后发送交换。查询的结果在 OUT 正文中返回:
如果您想一一处理行而不是一次处理整个 ResultSet,则需要使用 Splitter EIP,例如:
from("direct:hello") // here we split the data from the testdb into new messages one by one // so the mock endpoint will receive a message per row in the table // the StreamList option allows to stream the result of the query without creating a List of rows // and notice we also enable streaming mode on the splitter .to("jdbc:testdb?outputType=StreamList") .split(body()).streaming() .to("mock:result");
示例 - 每分钟轮询一次数据库
如果我们想使用 JDBC 组件轮询数据库,我们需要将其与轮询调度程序(例如Timer或Quartz等)结合使用。 在以下示例中,我们每 60 秒从数据库中检索数据:
from("timer://foo?period=60000") .setBody(constant("select * from customer")) .to("jdbc:testdb") .to("activemq:queue:customers");
示例 - 在数据源之间移动数据
一个常见的用例是查询数据、处理数据并将其移动到另一个数据源(ETL 操作)。在以下示例中,我们每小时从源表中检索新客户记录,过滤/转换它们并将它们移动到目标表:
from("timer://MoveNewCustomersEveryHour?period=3600000") .setBody(constant("select * from customer where create_time > (sysdate-1/24)")) .to("jdbc:testdb") .split(body()) .process(new MyCustomerProcessor()) //filter/transform results as needed .setBody(simple("insert into processed_customer values('${body[ID]}','${body[NAME]}')")) .to("jdbc:testdb");
SPRING BOOT 自动配置
在 Spring Boot 中使用 jdbc 时,请确保使用以下 Maven 依赖项来支持自动配置:
<dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-jdbc-starter</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency>
该组件支持 4 个选项,如下所列。
名称 | 描述 | 默认 | 类型 |
---|---|---|---|
camel.component.jdbc.autowired-enabled | 是否启用自动装配。这用于自动自动装配选项(该选项必须标记为自动装配),通过在注册表中查找是否存在匹配类型的单个实例,然后在组件上进行配置。这可用于自动配置 JDBC 数据源、JMS 连接工厂、AWS 客户端等。 | true | Boolean |
camel.component.jdbc.connection-strategy | 使用自定义策略处理连接。使用 spring-jdbc 组件时不要使用自定义策略,因为默认情况下使用特殊的 Spring ConnectionStrategy 来支持 Spring Transactions。该选项是 org.apache.camel.component.jdbc.ConnectionStrategy 类型。 | ConnectionStrategy | |
camel.component.jdbc.enabled | 是否启用 jdbc 组件的自动配置。这是默认启用的。 | Boolean | |
camel.component.jdbc.lazy-start-producer | 生产者是否应该懒惰地启动(在第一条消息上)。通过延迟启动,您可以使用它来允许 CamelContext 和路由在生产者可能在启动过程中失败并导致路由启动失败的情况下启动。通过延迟启动延迟,启动失败可以在通过 Camel 的路由错误处理程序路由消息期间处理。请注意,当处理第一条消息时,创建和启动生产者可能需要一些时间并延长处理的总处理时间。 | false | Boolean |