2012-08-28 20 views
9

Recientemente estaba usando Mybatis3 y encontré que cuando su instrucción SQL obtiene un conjunto de resultados vacío de la base de datos, Mybatis crea un nuevo List y lo devuelve a su programa.¿Cómo está lidiando MyBatis con un conjunto de resultados vacío?

dado algunas código, como:

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

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

suponer que el SQL anterior devuelve ningún filas (es decir, no hay ID mayores que 100).

La variable resultList estará entonces vacía List, pero quiero que sea null en su lugar. ¿Cómo puedo hacer eso?

Respuesta

15

Es mejor tener una colección vacía en lugar de nula como resultado de su consulta. Cuando se trabaja con una colección que suele recorrer cada elemento y hacer algo con él, algo como esto:

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

que no hacer nada si la lista está vacía.

Pero si vuelve nula, usted tiene que proteger su código contra NullPointerExceptions y escribir código como este en su lugar:

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

El primer enfoque es generalmente mejor y MyBatis lo hace así, pero que podría forzarlo para devolver nulo, si eso es realmente lo que quieres.

Para eso, puede escribir un MyBatis plugin e interceptar llamadas a cualquier consulta y luego devolver nulo si el resultado de la consulta está vacío.

Aquí hay un código:

En el complemento de configuración:

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

El código interceptor:

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) { 
    } 
} 

A continuación, podría limitar aún más el alcance del interceptor si interceptar llamadas a ResultSetHandler en lugar de Executor.

1

Siempre es mejor utilizar la lista vacía en lugar de nulo por los siguientes motivos.

El uso descuidado de null puede causar una asombrosa variedad de errores.

Además, null es desagradablemente ambiguo. Rara vez es obvio lo que se supone que significa un valor de retorno nulo, por ejemplo, Map.get (clave) puede devolver nulo ya sea porque el valor en el mapa es nulo, o el valor no está en el mapa. Null puede significar fracaso, puede significar éxito, puede significar casi cualquier cosa. Usar algo que no sea nulo aclara tu significado.

good discussion about null usage

Cuestiones relacionadas