package com.littlenb.mybatisjpa.rs; import com.littlenb.mybatisjpa.util.FieldReflectUtil; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.persistence.Entity; import javax.persistence.Table; import org.apache.ibatis.executor.resultset.DefaultResultSetHandler; import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ResultMap; 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.Configuration; /** * @author sway.li **/ @Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class})}) public class ResultTypePlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { if (invocation.getTarget() instanceof DefaultResultSetHandler) { DefaultResultSetHandler resultSetHandler = (DefaultResultSetHandler) invocation.getTarget(); Object[] args = invocation.getArgs(); Statement stmt = (Statement) args[0]; MappedStatement mappedStatement = (MappedStatement) FieldReflectUtil .getFieldValue(resultSetHandler, "mappedStatement"); List<ResultMap> resultMaps = mappedStatement.getResultMaps(); if (resultMaps != null && !resultMaps.isEmpty()) { ResultMap resultMap = resultMaps.get(0); if (resultMap.getResultMappings() == null || resultMap.getResultMappings().isEmpty()) { if (resultMap.getType().isAnnotationPresent(Entity.class) || resultMap.getType() .isAnnotationPresent(Table.class)) { ResultMapParser parser = ResultMapParserHolder .getInstance(mappedStatement.getConfiguration()); ResultMap newResultMap = parser .reloadResultMap(mappedStatement.getResource(), resultMap.getId(), resultMap.getType()); List<ResultMap> newResultMaps = new ArrayList<>(); newResultMaps.add(newResultMap); FieldReflectUtil.setFieldValue(mappedStatement, "resultMaps", newResultMaps); // modify the resultMaps FieldReflectUtil.setFieldValue(resultSetHandler, "mappedStatement", mappedStatement); } } } // return resultSetHandler.handleResultSets(stmt); } return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } /** * Use static inner classes ensure thread safety */ private static class ResultMapParserHolder { private static Map<String, ResultMapParser> parsers = new HashMap<>(); static ResultMapParser getInstance(Configuration configuration) { String id = configuration.getEnvironment().getId(); if (!parsers.containsKey(id)) { parsers.put(id, new ResultMapParser(configuration)); } return parsers.get(id); } } }