MyBatis 如何处理空的结果集?

2022-09-04 07:52:43

最近我正在使用Mybatis3,发现当您的SQL语句从数据库中获取空结果集时,Mybatis会创建一个新的结果集并将其返回到您的程序中。List

给定一些代码,例如:

List<User> resultList = (List<User>)sqlSession.select("statementId");

<select id="statementId" resultType="User">
   select * from user where id > 100
</select>

假设上述 SQL 不返回任何行(即没有大于 100 的 id)。

然后变量将是空的,但我希望它是。我该怎么做?resultListListnull


答案 1

最好是使用空集合,而不是 null 作为查询的结果。使用集合时,您通常会遍历每个项目并对它执行一些操作,如下所示:

List<User> resultList = (List<User>) sqlSession.select("statementId");
for (User u : resultList) { 
   //... 
}

如果列表为空,则不会执行任何操作。

但是,如果返回 null,则必须保护代码免受 NullPointerExceptions 的侵害,并编写如下代码:

List<User> resultList = (List<User>) sqlSession.select("statementId");
if (resultList != null) {
  for (User u : resultList) { 
     //... 
  }
}

第一种方法通常更好,MyBatis就是这样做的,但是你可以强制它返回null,如果这真的是你想要的。

为此,您可以编写一个MyBatis插件并拦截对任何查询的调用,如果查询结果为空,则返回null。

下面是一些代码:

在您的配置中添加:

<plugins>
   <plugin interceptor="pack.test.MyInterceptor" />
</plugins>

拦截器代码:

package pack.test;

import java.util.List;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

@Intercepts({ @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) })
public class MyInterceptor implements Interceptor {
    public Object intercept(Invocation invocation) throws Throwable {
        Object result = invocation.proceed();
        List<?> list = (List<?>) result;
        return (list.size() == 0 ? null : result);
    }

    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties properties) {
    }
}

然后,如果将调用截获为 而不是 ,则可以进一步限制侦听器的作用域。ResultSetHandlerExecutor


答案 2

出于以下原因,最好使用空列表而不是 null。

粗心使用 null 可能会导致各种各样的错误。

此外,null 是令人不快的模棱两可。null 返回值的含义很少很明显 - 例如,Map.get(key) 可以返回 null,因为映射中的值为 null,或者值不在映射中。Null可以表示失败,可以意味着成功,几乎可以表示任何事情。使用 null 以外的其他内容可以清楚地说明您的含义。

关于空用法的良好讨论


推荐