如果有t1到t20张表,如何优化xml拼接 UNION ALL 的 SQL

当有 t1 到 t20 张表,要在 MyBatis 的动态 XML 中根据用户传入条件选择表并拼接 UNION ALL 的 SQL 时,可以考虑以下几种优化方式,以提高代码的可读性和可维护性:

 

  1. 使用 <foreach> 标签简化 SQL 拼接
    可以使用 <foreach> 标签来遍历表名列表,动态生成 UNION ALL 部分的 SQL,而不是使用多个 <when> 标签来处理不同数量表的情况。
  2. 提取公共部分 SQL
    将 SELECT 语句的公共部分(如 SELECT id, name, value)提取出来,避免重复编写。
  3. 参数验证和默认处理
    增加对传入参数的验证和默认处理逻辑,确保在异常情况下也能返回合理的结果。

 

以下是优化后的 MyBatis XML 映射文件示例:

 

xml
 
 
<mapper namespace="com.example.dao.DataMapper">
    <select id="selectData" resultType="com.example.entity.DataEntity">
        <!-- 公共的 SELECT 部分 -->
        <sql id="commonSelect">
            SELECT id, name, value
        </sql>
        
        <choose>
            <when test="tableNames != null and tableNames.size() > 0">
                <trim prefix="" suffixOverrides="UNION ALL">
                    <foreach collection="tableNames" item="tableName" separator="UNION ALL">
                        <include refid="commonSelect" />
                        FROM ${tableName}
                        <where>
                            <!-- 可以根据需要添加其他条件 -->
                        </where>
                    </foreach>
                </trim>
            </when>
            <otherwise>
                <!-- 如果没有传入表名,返回空结果 -->
                <include refid="commonSelect" />
                FROM t1 WHERE 1 = 0
            </otherwise>
        </choose>
        ORDER BY value DESC
        LIMIT #{offset}, #{limit}
    </select>
</mapper>
 

 

对应的 DataMapper 接口和 DataService 类的代码基本保持不变:

 

java
 
 
import java.util.List;
import java.util.Map;

public interface DataMapper {
    List<DataEntity> selectData(Map<String, Object> params);
}
 

 

java
 
 
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class DataService {

    private final DataMapper dataMapper;

    public DataService(DataMapper dataMapper) {
        this.dataMapper = dataMapper;
    }

    public List<DataEntity> getData(List<String> tableNames, int offset, int limit) {
        Map<String, Object> params = new HashMap<>();
        params.put("tableNames", tableNames);
        params.put("offset", offset);
        params.put("limit", limit);
        return dataMapper.selectData(params);
    }
}
 

 

通过以上优化,代码更加简洁,并且能够适应更多数量的表,同时提高了代码的可维护性和扩展性。注意在实际应用中,要对 SQL 注入风险进行防范,尽量使用预编译语句。
posted @ 2025-05-08 14:19  CharyGao  阅读(30)  评论(0)    收藏  举报