Apache Camel 2.20.0 Mybatis组件使用consumer.useIterator时如何设置查询参数?
好问题!我之前在处理Camel结合MyBatis导出大数据量的场景时,也遇到过这个参数传递的困惑——毕竟MyBatis作为consumer(from端点)时,默认的轮询模式不像生产者(to端点)那样直接支持从Exchange传递参数。下面给你几个实用的解决方案,适配不同的场景:
方案1:使用
pollEnrich结合consumer.useExchangeParameters(推荐,动态参数友好) 这个方案适合需要动态参数的场景,通过pollEnrich将参数传递给MyBatis consumer,完美兼容consumer.useIterator的内存优化特性:
- 修改路由配置:用触发组件(比如
timer)作为入口,设置参数后通过pollEnrich调用MyBatis端点,开启consumer.useExchangeParameters=true让consumer从Exchange Header获取参数:
from("timer:dailyExport?period=86400000") // 每天触发一次,可按需调整周期 // 动态生成起始日期,比如调用工具类获取昨天的日期 .setHeader("startDate", method(DateUtils.class, "getYesterdayDate")) // 调用MyBatis consumer,开启参数传递开关 .pollEnrich("mybatis:selectItemsByDate?statementType=SelectList&consumer.useIterator=true&consumer.useExchangeParameters=true") // 拆分迭代器中的数据,逐行处理 .split(body()) .process(doSomething) .to("file:my-path-file");
- 配置MyBatis Mapper:确保Mapper接口的方法参数用
@Param注解指定参数名,和Camel Header的key完全对应:
public interface ItemMapper { List<Item> selectItemsByDate(@Param("startDate") String startDate); }
- 动态参数生成示例:如果需要每次触发的参数不同,比如每天导出前一天的数据,可以写一个简单的工具类:
public class DateUtils { public String getYesterdayDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -1); return sdf.format(cal.getTime()); } }
方案2:使用
consumer.parameter指定固定参数(适合参数固定的场景) 如果你的起始日期是固定值,或者可以从系统属性/环境变量获取,直接在端点URI中通过consumer.parameter指定即可:
from("mybatis:selectItemsByDate?statementType=SelectList&consumer.useIterator=true&consumer.parameter=startDate:2024-01-01") .split(body()) .process(doSomething) .to("file:my-path-file");
多个参数用逗号分隔,比如consumer.parameter=startDate:2024-01-01,endDate:2024-01-31。
方案3:手动使用
PollingConsumer控制参数(适合自定义触发逻辑) 如果需要完全自定义触发时机和参数逻辑,可以手动创建PollingConsumer,在代码中直接设置参数并触发查询:
// 初始化Camel上下文 CamelContext context = new DefaultCamelContext(); // 创建MyBatis端点并初始化PollingConsumer Endpoint mybatisEndpoint = context.getEndpoint("mybatis:selectItemsByDate?statementType=SelectList&consumer.useIterator=true"); PollingConsumer consumer = mybatisEndpoint.createPollingConsumer(); consumer.start(); // 构造Exchange并设置查询参数 Exchange exchange = consumer.createExchange(); exchange.getIn().setHeader("startDate", "2024-01-01"); // 这里可以动态生成参数 // 触发查询并获取迭代器结果 Exchange resultExchange = consumer.receive(exchange); Iterator<Item> itemIterator = resultExchange.getIn().getBody(Iterator.class); // 逐行处理数据 while (itemIterator.hasNext()) { Item item = itemIterator.next(); // 执行自定义处理逻辑 doSomething.process(new DefaultExchange(context).getIn().setBody(item)); // 写入文件逻辑... } // 关闭资源 consumer.stop(); context.stop();
关键注意事项
consumer.useIterator=true会让MyBatis返回Iterator而非List,避免一次性加载大量数据到内存,这正是你需要的内存友好模式。consumer.useExchangeParameters=true是核心配置,开启后MyBatis consumer会从Exchange的In消息Header中读取参数,匹配Mapper中@Param指定的参数名。- 如果使用XML配置的MyBatis statement,确保XML中的参数名和Header key一致,比如:
<select id="selectItemsByDate" resultType="com.example.Item"> SELECT * FROM items WHERE create_time >= #{startDate} </select>
内容的提问来源于stack exchange,提问作者Oibaf
相关产品推荐
相关产品推荐

