Ignite三个缓存UNION ALL联合查询报错及正确实现方式问询
问题原因
你遇到的报错由两个核心问题导致:
- 跨缓存查询的schema引用规则错误:Ignite中每个开启了SQL功能的缓存,默认对应的SQL schema名称就是缓存自身的名称。如果缓存名包含小写字符、特殊符号,SQL解析时会默认将未加引号的标识符转为全大写,导致和实际缓存名匹配失败,触发schema不存在的报错。
- SQL语法缺失:你写的查询逻辑中,第二个SELECT语句和第三个SELECT语句之间漏写了
UNION ALL关键字,也会导致SQL解析失败。
正确实现方式
前置校验
首先要确保三个缓存创建时都开启了SQL功能,也就是对应的CacheConfiguration中已经通过setIndexedTypes注册了对应的实体类(ConfirmedEvent、UnconfirmedEvent)。
修正后的代码实现
// 先生成三个缓存的实际名称 String confirmedCacheName = String.format(CONFIRMED_EVENT_CACHE, mcId); String nonUrgentCacheName = String.format(UNCONFIRMED_NON_URGENT_EVENT_CACHE, mcId); String urgentCacheName = String.format(UNCONFIRMED_URGENT_EVENT_CACHE, mcId); int afibType = AnnotationConverter.StringToRhythmValue(AFIB); // 构造SQL,缓存名用双引号包裹避免大小写转换,补全缺失的UNION ALL String EVENT_GET_RHYTHM_BY_ID = "SELECT timestamp FROM ConfirmedEvent " + "WHERE orderId = ? AND startTime < ? AND endTime > ? AND type = ? " + "UNION ALL " + "SELECT timestamp FROM \"" + nonUrgentCacheName + "\".UnconfirmedEvent " + "WHERE orderId = ? AND startTime < ? AND endTime > ? AND type = ? " + "UNION ALL " + "SELECT timestamp FROM \"" + urgentCacheName + "\".UnconfirmedEvent " + "WHERE orderId = ? AND startTime < ? AND endTime > ? AND type = ? " + "ORDER BY startTime"; // 传递查询参数,按SQL中占位符的顺序依次传入即可 SqlFieldsQuery sql_Afib = new SqlFieldsQuery(EVENT_GET_RHYTHM_BY_ID) .setArgs( // 第一个SELECT的参数 orderId, endTimestamp, startTimestamp, afibType, // 第二个SELECT的参数 orderId, endTimestamp, startTimestamp, afibType, // 第三个SELECT的参数 orderId, endTimestamp, startTimestamp, afibType ); List<Long> EventsEndTime = new ArrayList<>(); // 用任意一个同实例下的缓存执行查询都可以,不需要和SQL里的表绑定 try (QueryCursor<List<?>> cursor = confirmedEventCache.query(sql_Afib)) { for (List<?> row : cursor) { EventsEndTime.add((Long) row.get(0)); } }
补充注意事项
- 如果你创建缓存时通过
setSqlSchema自定义了schema名称,直接用自定义的schema名代替上面代码中的缓存名即可。 - 所有可变查询条件都通过
setArgs传递,不要用String.format拼接,避免SQL注入风险。 - 三个缓存必须属于同一个Ignite实例,且执行查询时都处于活跃状态。
内容的提问来源于stack exchange,提问作者sachith
相关产品推荐
相关产品推荐

