2012-08-28 88 views
9

最近我使用Mybatis3,发现当你的SQL语句得到一个空的结果从数据库设置,MyBatis的创建一个新的List并返回给你的程序。MyBatis如何处理空的结果集?

鉴于一些代码,如:

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

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

假定上述SQL不返回行(即没有ID大于100)。

变量​​将是一个空的List,但我希望它是null而不是。 我该怎么做?

回答

15

最好是有一个空的集合,而不是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的plugin和拦截调用任何查询,然后返回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) { 
    } 
} 

然后,您可以进一步限制拦截的范围,如果你拦截来电到ResultSetHandler而不是Executor

1

它始终是更好地使用空列表而不是空,原因如下。

使用不慎空,则可能导致惊人的各种错误。

此外,null很不明确。很少有人明白空返回值应该是什么意思 - 例如,Map.get(key)可以返回null,因为map中的值为null,或者该值不在map中。空可能意味着失败,可能意味着成功,几乎意味着任何事情。使用除null之外的其他内容可以明确您的意思。

good discussion about null usage