多UNION操作SQL查询构建及MyBatis trim前缀覆盖失效问题咨询
1. 为什么的prefixOverrides去除开头UNION失效?
你提到的节点解析顺序问题是核心原因:MyBatis的节点解析是从外到内的。外层
2. 与的执行顺序
3. 更简洁的多UNION查询构建方式
方案一:用自动生成UNION分隔符
这是最省心的实现方式,把需要关联的表名放到集合参数中,通过separator="UNION"后,MyBatis会自动在查询之间插入UNION,完全不会出现多余的开头或结尾:
<select id="queryUnionData" resultType="YourResultType"> <foreach collection="tableNames" item="tableName" separator="UNION" open="" close=""> SELECT col1, col2 FROM `${tableName}` WHERE status = 1 </foreach> </select>
调用时传入tableNames集合(比如Arrays.asList("table_a", "table_b", "table_c")),就能生成SELECT ... FROM table_a UNION SELECT ... FROM table_b UNION ...的标准SQL。
方案二:调整SQL片段结构,用修剪末尾UNION
如果不想用suffixOverrides去掉最后一个多余的UNION,避开解析顺序的问题:
<sql id="unionQuery"> SELECT col1, col2 FROM ${tableName} WHERE status = 1 UNION </sql> <select id="queryUnionData" resultType="YourResultType"> <trim suffixOverrides="UNION"> <include refid="unionQuery"> <property name="tableName" value="table_a"/> </include> <include refid="unionQuery"> <property name="tableName" value="table_b"/> </include> <include refid="unionQuery"> <property name="tableName" value="table_c"/> </include> </trim> </select>
这种方式下,
方案三:用Provider方法构建SQL
如果动态逻辑复杂(比如需要根据不同表调整查询条件),可以使用MyBatis的@SelectProvider注解,在Java代码中直接拼接SQL,灵活性更高:
@SelectProvider(type = UnionSqlProvider.class, method = "buildUnionQuery") List<YourResultType> queryUnionData(List<String> tableNames); class UnionSqlProvider { public String buildUnionQuery(List<String> tableNames) { StringBuilder sql = new StringBuilder(); for (int i = 0; i < tableNames.size(); i++) { sql.append("SELECT col1, col2 FROM ").append(tableNames.get(i)).append(" WHERE status = 1"); if (i != tableNames.size() - 1) { sql.append(" UNION "); } } return sql.toString(); } }
内容的提问来源于stack exchange,提问作者Adrian Elwer

