为什么Mybatis在查询单个字段时却返回了整个对象?

最近基于mybatis,新建一个父类接口,想快速实现所有表查询最后更新时间的功能

public interface MyBaseMapper<T> {
    @SelectProvider(
            type = LastUpdateTimeProvider.class,
            method = "getLastUpdateTime"
    )
    LocalDateTime getLastUpdateTime(Class<T> clazz);
}
@UtilityClass
public class LastUpdateTimeProvider {
    public String getLastUpdateTime(Class<? extends BaseEntity> clazz) {
        return "select max(update_time) from " + getTableName(clazz);
    }

    public String getTableName(Class<?> modelClass) {
        Table table = modelClass.getAnnotation(Table.class);
        if (table != null) {
            return table.name();
        }
        return modelClass.getName();
    }
}

最后生成的SQL类似于:

select max(update_time) from t_xxx

以获取最后一次数据更新的时间戳。直接查询数据库,所有表的查询结果都不为空。

但通过Mybatis执行的时候,总是返回null,不得其解。

我做了以下尝试:

  1. 去掉了MyBaseMapper,直接在子类中使xml的方式完成查询,并且修改了sql

     <select id="getLastUpdateTime" resultType="java.time.LocalDateTime">
         select update_time from t_xxx order by update_time limit 1;
     </select>

    这样查询Mybatis会返回对象xxx,而不是LocalDateTime,错误如下:

    java.lang.ClassCastException: com.abc.def.Xxx cannot be cast to java.time.LocalDateTime
  2. 去掉了自定义的一些Interceptor,排除干扰;
  3. debug追溯Mybatis的源码;

    1. 首先追踪到org.mybatis:mybatis:3.4.6这个包中的org.apache.ibatis.binding.MapperMethod的第83行result = sqlSession.selectOne(command.getName(), param);
    2. 一路debug,直到org.apache.ibatis.session.Configuration的第721行return mappedStatements.get(id);
    3. 这时候就发现,这个mappedStatements对象中,已经缓存好了我这个查询id,我在IDEA的watches中查看结果集,就发现mappedStatements.get("com.abc.def.XxxMapper.getLastUpdateTime")resultMaps有两个值,第一个值为Xxx对象,第二个值为LocalDateTime,对于这个mappedStatements如何生成的,我暂时还不太了解,在提出这个问题以后,我再继续了解一下,看能否从这里解决问题;
    4. 后面的代码就没啥了,就直接根据这个resultMaps生成结果,然后再返回
阅读 1.7k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题