/** * Copyright © 2015-2020 JeePlus All rights reserved. */ package com.jeeplus.common.persistence.proxy; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.binding.BindingException; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; import com.jeeplus.common.persistence.Page; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** *

* 执行代理类,扩展Mybatis的方式来让其Mapper接口来支持. *

* * @author poplar.yfyang * @version 1.0 2012-05-13 上午10:09 * @since JDK 1.5 */ public class PaginationMapperMethod { private final SqlSession sqlSession; private final Configuration config; private SqlCommandType type; private String commandName; private String commandCountName; private final Class declaringInterface; private final Method method; private Integer rowBoundsIndex; private Integer paginationIndex; private final List paramNames; private final List paramPositions; private boolean hasNamedParameters; public PaginationMapperMethod(Class declaringInterface, Method method, SqlSession sqlSession) { paramNames = new ArrayList(); paramPositions = new ArrayList(); this.sqlSession = sqlSession; this.method = method; this.config = sqlSession.getConfiguration(); this.declaringInterface = declaringInterface; this.hasNamedParameters = false; setupFields(); setupMethodSignature(); setupCommandType(); validateStatement(); } /** * 代理执行方法。 * * @param args 参数信息 * @return 执行结果 */ @SuppressWarnings("unchecked") public Object execute(Object[] args) { final Object param = getParam(args); Page page; RowBounds rowBounds; if (paginationIndex != null) { page = (Page) args[paginationIndex]; rowBounds = new RowBounds(page.getFirstResult(), page.getMaxResults()); } else if (rowBoundsIndex != null) { rowBounds = (RowBounds) args[rowBoundsIndex]; page = new Page(); } else { throw new BindingException("Invalid bound statement (not found rowBounds or pagination in paramenters)"); } page.setCount(executeForCount(param)); page.setList(executeForList(param, rowBounds)); return page; } /** * 执行总数的方法,调用方法执行计算总数,取得总结果 * * @param param 参数信息 * @return 查询的总记录数 */ private long executeForCount(Object param) { Number result = (Number) sqlSession.selectOne(commandCountName, param); return result.longValue(); } /** * 取得分页的执行结果,返回的是纪录信息 * * @param param 参数 * @param rowBounds row * @return 纪录列表 */ private List executeForList(Object param, RowBounds rowBounds) { return sqlSession.selectList(commandName, param, rowBounds); } /** * 取得当前执行的参数信息 * * @param args 参数 * @return 参数信息 */ private Object getParam(Object[] args) { final int paramCount = paramPositions.size(); if (args == null || paramCount == 0) { return null; } else if (!hasNamedParameters && paramCount == 1) { return args[paramPositions.get(0)]; } else { Map param = new HashMap(); for (int i = 0; i < paramCount; i++) { param.put(paramNames.get(i), args[paramPositions.get(i)]); } return param; } } private void setupMethodSignature() { final Class[] argTypes = method.getParameterTypes(); for (int i = 0; i < argTypes.length; i++) { if (Page.class.isAssignableFrom(argTypes[i])) { paginationIndex = i; } else if (RowBounds.class.isAssignableFrom(argTypes[i])) { rowBoundsIndex = i; } else { String paramName = String.valueOf(paramPositions.size()); paramName = getParamNameFromAnnotation(i, paramName); paramNames.add(paramName); paramPositions.add(i); } } } private String getParamNameFromAnnotation(int i, String paramName) { Object[] annotations = method.getParameterAnnotations()[i]; for (Object annotation : annotations) { if (annotation instanceof Param) { hasNamedParameters = true; paramName = ((Param) annotation).value(); } } return paramName; } /** * 设置当前的查询总记录数的ID */ private void setupFields() { commandName = declaringInterface.getName() + "." + method.getName(); commandCountName = commandName + "Count"; // 命名约定 } /** * 设置当前的参数的类型信息 */ private void setupCommandType() { MappedStatement ms = config.getMappedStatement(commandName); type = ms.getSqlCommandType(); if (type != SqlCommandType.SELECT) { throw new BindingException("Unsupport execution method for: " + commandName); } } /** * 验证Statement */ private void validateStatement() { if (!config.hasStatement(commandName)) { throw new BindingException("Invalid bound statement (not found): " + commandName); } if (!config.hasStatement(commandCountName)) { throw new BindingException("Invalid bound statement (not found): " + commandCountName); } } }