All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.aly8246.collectionutil.main.CollectionInterceptor Maven / Gradle / Ivy

Go to download

Collection Util is a mybatis plug-in designed to solve the problem of N + 1 in mysql. When you use Mysql to query linked tables and pages, there will be n + 1 problem. This plug-in can help you!

The newest version!
package com.github.aly8246.collectionutil.main;

import com.github.aly8246.collectionutil.core.PageInterface;
import com.github.aly8246.collectionutil.core.impl.MysqlPageImpl;
import com.github.aly8246.collectionutil.exception.CollectionException;
import com.github.aly8246.collectionutil.result.PageResult;
import com.github.aly8246.collectionutil.model.Index;
import com.github.aly8246.collectionutil.model.Limit;
import com.github.aly8246.collectionutil.model.Page;
import com.github.aly8246.collectionutil.util.CollectionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.stream.Collectors;


@Intercepts(
		{
				@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, org.apache.ibatis.session.ResultHandler.class}),
				@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
		}
)
@RequiredArgsConstructor
@Slf4j
public class CollectionInterceptor implements Interceptor {

private PageInterface pageInterface;

/**
 * 存储分页返回结果
 *
 * @author 南有乔木
 * @version v.1.0.2
 * @see CollectionUtil
 */
protected static ThreadLocal pageResultThreadLocal = new ThreadLocal<>();

@Override
public Object intercept(Invocation invocation) throws Throwable {
	Object[] args = invocation.getArgs();
	MappedStatement ms = (MappedStatement) args[0];
	Object sqlParamObj = args[1];
	Map sqlParamMap;
	try {
		sqlParamMap = (Map) sqlParamObj;
	} catch (Exception e) {
		return invocation.proceed();
	}
	
	RowBounds rowBounds = (RowBounds) args[2];
	ResultHandler resultHandler = (ResultHandler) args[3];
	Executor executor = (Executor) invocation.getTarget();
	CacheKey cacheKey;
	BoundSql boundSql;
	
	if (args.length == 4) {
		boundSql = ms.getBoundSql(sqlParamObj);
		cacheKey = executor.createCacheKey(ms, sqlParamObj, rowBounds, boundSql);
	} else {
		cacheKey = (CacheKey) args[4];
		boundSql = (BoundSql) args[5];
	}
	
	String className = this.getClassName(ms.getId());
	String methodName = this.getMethodName(ms.getId());
	
	Class clazz = Class.forName(className);
	
	List methodList = Arrays.stream(clazz.getMethods())
			                          .filter(e -> e.getName().equals(methodName))
			                          .collect(Collectors.toList());
	if (methodList.size() > 0) {
		List parameterList = Arrays
				                                .stream(methodList
						                                        .get(0)
						                                        .getParameters())
				                                .collect(Collectors.toList());
		
		for (Parameter param : parameterList) {//如果参数中有分页类
			if (param.getType().getName().equals(Page.class.getName())) {
				//需要分页
				log.info("CollectionInterceptor running!");
				log.debug("className:" + className);
				log.debug("methodName:" + methodName);
				Page page = this.getPageByParam(sqlParamMap);
				log.debug("page:" + page);
				List indexList = pageInterface.getIndexList(ms, executor, sqlParamObj, boundSql, rowBounds, resultHandler);
				log.debug("indexList:" + indexList);
				Limit limit = pageInterface.Limit(indexList, page);
				log.debug("limit:" + limit);
				
				if (limit != null)//数量满足条件,可以进行分页
				{
					List query = pageInterface.query(ms, executor, sqlParamObj, boundSql, rowBounds, resultHandler, cacheKey, limit);
					PageResult pageResult = new PageResult();
					pageResult.setPage(page.getPage());
					pageResult.setPageSize(page.getPageSize());
					pageResult.setData(query);
					pageResult.setTotalPage((indexList.size() + page.getPageSize() - 1) / page.getPageSize());
					pageResult.setTotal(indexList.size());
					pageResultThreadLocal.set(pageResult);
					log.debug("success: " + pageResult);
					log.info("run success!");
					return query;
				}
			}
		}
	}
	
	return invocation.proceed();
	
}


@Override
public Object plugin(Object target) {
	log.info("Collection-util active!");
	return Plugin.wrap(target, this);
}

@Override
public void setProperties(Properties properties) {
	this.setPageInterface(properties.getProperty("database"));
}

private void setPageInterface(String database) {
	//默认注入mysql实现类
	this.pageInterface = new MysqlPageImpl();
	
	if (database.equals("mysql")) this.pageInterface = new MysqlPageImpl();
}

/**
 * 从msId中获取执行类路径
 *
 * @param s msId
 * @return 执行类路径
 * @throws CollectionException 获取失败
 * @author 南有乔木
 */
private String getClassName(String s) {
	if (s.length() <= 0)
		throw new CollectionException("Get class name error!please contact [email protected]");
	List pathList = Arrays
			                        .stream(s.split("\\."))
			                        .collect(Collectors.toCollection(LinkedList::new));
	pathList.remove(pathList.size() - 1);//移除方法名
	
	return String.join(".", pathList);
}

/**
 * 从msId中获取执行方法
 *
 * @param s msId
 * @return 执行方法
 * @throws CollectionException 获取失败
 * @author 南有乔木
 */
private String getMethodName(String s) {
	if (s.length() <= 0)
		throw new CollectionException("Get method name error!please contact [email protected]");
	List pathList = Arrays
			                        .stream(s.split("\\."))
			                        .collect(Collectors.toCollection(LinkedList::new));
	
	return pathList.get(pathList.size() - 1);
}

/**
 * 获取Page对象,里面有分页信息
 *
 * @param o mapper接口上的所有参数
 * @return Page对象
 * @author 南有乔木
 */
private Page getPageByParam(Map o) {
	System.out.println(o);
	Page page = new Page();
	for (Map.Entry entry : o.entrySet()) {
		try {
			page = (Page) entry.getValue();
			if (page != null) return page;
		} catch (Exception ignored) {
		}
	}
	return page;
}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy