select * from users where id in ()
查询如上所示。
<select id="getByIds" resultMap="BaseResultMap">
SELECT
<include refid="BaseColumnList"/>
FROM users
WHERE id IN
<foreach item="id" collection="ids"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
如果Param ids
为空,Mybatis将抛出BadSqlGrammarException,生成类似“select * from users where id in
”的查询。
如果ids
为空,我如何跳过查询并返回空列表?
答案 0 :(得分:6)
如果ID为空,我如何跳过查询并返回空列表?
要跳过查询(不执行),请不要拨打Mybatis。 调用代码应检查 ids 是否为空:
return null == ids || ids.isEmpty() ? new ArrayList<User>() : session.select("getByIds", ids);
这正是问题中提出的问题。
如果你真的希望Mybatis处理这个问题,那么生成的查询必须是有效的,因为必须执行(然后不要跳过)才能快速返回空结果 。这意味着忘记像id = <!-- a value that will never exist in the table -->
这样的东西,因为它肯定会涉及(自由和无用的)全扫描来搜索未存在的值。
然后:
WHERE
<choose>
<when test="ids==null || ids.isEmpty()">
1 = 0 <!-- a test returning false, to adapt depending on you DB vendor -->
</when>
<otherwise>
id IN <foreach item="id" collection="ids" open="(" separator="," close=")">#{id}</foreach>
</otherwise>
</choose>
确认的另一个选择是使用拦截器来取消&#34;取消&#34;在执行之前的查询,但这肯定是在这里必须实现的内容的过度复杂。
答案 1 :(得分:2)
java代码功能
List<ApiPriceChlogEntity> getApiAndDevPrice(@Param("apiKeys") List<String> currentApiKey, @Param("devKeys") List<String> currentDevKey, @Param("startDate") Date startDate);
映射器文件
<select id="getApiAndDevPrice" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM t_api_price_chlog tab1
<where>
<if test="apiKeys.size() > 0">
tab1.api_key IN
<foreach collection="apiKeys" item="item" separator="," open="(" close=")" index="">
#{item}
</foreach>
</if>
<if test="devKeys.size() > 0">
AND tab1.dev_key IN
<foreach collection="devKeys" item="item" separator="," open="(" close=")" index="">
#{item}
</foreach>
</if>
<if test="startDate != null">
AND tab1.change_date >= #{startDate}
</if>
</where>
我测试过,希望能帮到你。
答案 2 :(得分:0)
使用mybatis拦截器,创建一个n PreparedStatement对象,然后将其返回。
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
@Slf4j
public class MyBatisInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
//...your code
//return invocation.proceed();
return new NullExecutor();
}
}
MyBatis要获取PreparedStatement对象作为返回值,“ NullExecutor”为:
public class NullExecutor implements PreparedStatement {}
什么都不做,只写几件事,就像:
@Override
public void setDouble(int parameterIndex, double x) throws SQLException {
//empty here
}
@Override
public boolean execute() throws SQLException {
//it's ok,do noting.
return false;
}
...etc
添加您的配置:
@Bean
public MyBatisInterceptor myBatisInterceptor() {
return new MyBatisInterceptor();
}
您需要在Interceptor中获取“ BoundSql”,然后才能获取sql和args,只需对其进行谷歌搜索即可。
我不确定它是否可以正常工作,只是为了学习。
答案 3 :(得分:-1)
使用测试:
<select id="getByIds" resultMap="BaseResultMap">
SELECT
<include refid="BaseColumnList"/>
FROM users
<if test="ids!= null">
WHERE id IN
<foreach item="id" collection="ids"
open="(" separator="," close=")">
#{id}
</foreach>
</if>
</select>