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

com.github.antelopeframework.mybatis.criterion.plugin.CriteriaPlugin Maven / Gradle / Ivy

There is a newer version: 1.1.5
Show newest version
package com.github.antelopeframework.mybatis.criterion.plugin;

import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
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;

import com.github.antelopeframework.mybatis.criterion.CriteriaQueryTranslator;
import com.github.antelopeframework.mybatis.criterion.TypedValue;
import com.github.antelopeframework.mybatis.paged.PagedQueryRunner;

/**
 * MyBatis Criteria Query Plugin. 
* *

功能说明:

*
* * 拦截MyBatis的两个方法执行: *
    *
  • {@link Executor#query(MappedStatement, Object, RowBounds, ResultHandler)}
  • *
  • {@link StatementHandler#query(Statement, ResultHandler)}
  • *
* * 配置方式:
* *
 * <plugins>
 * 	<plugin interceptor="com.github.antelopeframework.mybatis.criterion.plugin.CriteriaPlugin"></plugin>
 * </plugins>
 * 
* *

分页插件:

*
* * 分页插件可选配com.github.pagehelper使用; pagehelper的maven依赖配置为: *
 * <dependency>
 * 	<groupId>com.github.pagehelper</groupId>
 * 	<artifactId>pagehelper</artifactId>
 * 	<version>4.1.3</version>
 * </dependency>
 * 
* * 使用此分页插件时, 注意配置顺序: com.github.pagehelper.PageHelper要配置在{@lin CriteriaPlugin}后边。 *
 * <plugins>
 * 	<plugin interceptor="com.github.antelopeframework.mybatis.criterion.plugin.CriteriaPlugin"></plugin>
 * 	<plugin interceptor="com.github.pagehelper.PageHelper"></plugin>
 * </plugins>
 * 
* *

示例:

*
* * MyBatis XML 配置: * *
 * <mapper namespace="----">
 * 	<sql id="criteriaQueryCondition">
 * 		<if test="@com.github.antelopeframework.mybatis.criterion.plugin.CriteriaPlugin@isCriteriaQuery()">
 * 			${com.github.antelopeframework.mybatis.criterion.plugin.CriteriaPlugin@getQueryCondition()}
 * 		</if>
 * 	</sql>

 * 	<select id="findByCriteria" resultType="hashmap">
 * 		select * from t_test_table <include refid="criteriaQueryCondition"></include>
 * 	</select>
 * </mapper>
 * 
* * java 代码: * *
 * 	List findByCriteria(@ShardOnTrkPoint String shard, Criteria criteria);
 * 
 * 
 * 使用Criteria查询时, 其他参数都会失效, 仅使用Criteria中的参数作为查询约束.
 * 
 * 分页查询的使用方法请参考: {@link PagedQueryRunner}
 * 
 * @author yangzhi.yzh
 *
 */
@Intercepts( {  
    @Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }),
    @Signature(method = "query", type = StatementHandler.class, args = { Statement.class, ResultHandler.class }),
})
public class CriteriaPlugin implements Interceptor {
	
	/**
	 * 是否为Criteria Query.
	 * 
	 * @return
	 */
	public static boolean isCriteriaQuery() {
		InterceptorContext context = InterceptorContextHelper.get();
		return context == null ? false : context.isCriteriaQuery();
	} 
	
	/**
	 * 
	 * @return
	 */
	public static String getQueryCondition() {
		InterceptorContext context = InterceptorContextHelper.get();
		CriteriaQueryTranslator queryTranslator = context == null ? null : context.getQueryTranslator();
		
		return queryTranslator == null ? "" : queryTranslator.getQueryCondition();
	}
	
	/**
	 * 
	 * @return
	 */
	public static TypedValue[] getQueryParams() {
		InterceptorContext context = InterceptorContextHelper.get();
		CriteriaQueryTranslator queryTranslator = context == null ? null : context.getQueryTranslator();
		
		return queryTranslator != null ? queryTranslator.getQueryParams() : null;
	}
	
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		InterceptorContextHelper.setContext();
		
		try {
			Object target = invocation.getTarget();
			if (target instanceof Executor) {
				return doExecutorIntercept(invocation);
			} else {
				return doStatementHandlerIntercept(invocation);
			}
		} finally {
			InterceptorContextHelper.removeContext();
		}
	}

	/**
	 * 
	 * @param invocation
	 * @return
	 * @throws Throwable
	 */
	private Object doExecutorIntercept(Invocation invocation) throws Throwable {
		InterceptorContext context = InterceptorContextHelper.get();

		//~ Criteria查询逻辑
		context.initCriteriaQuery(null, invocation);
		
		//~ 分页插件逻辑
		context.initPagedQuery(invocation);
		
		return invocation.proceed();
	}
	
	/**
	 * 
	 * @param invocation
	 * @return
	 * @throws Throwable
	 */
	private Object doStatementHandlerIntercept(Invocation invocation) throws Throwable {
		InterceptorContext context = InterceptorContextHelper.get();
		
		Statement stm = (Statement) invocation.getArgs()[0];
		if (stm instanceof PreparedStatement && context.isCriteriaQuery()) {
			PreparedStatement pstm = (PreparedStatement) stm;
			
			int index = 1;
			TypedValue[] queryParams = CriteriaPlugin.getQueryParams();
			if (queryParams != null) {
				for (TypedValue value : queryParams) {
					if (value == null) {
						continue;
					}
					
					//org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.util.Date. Use setObject() with an explicit Types value to specify the type to use.
					Object v = value.getValue();
					if (v != null && v instanceof java.util.Date) {
						java.util.Date date = (java.util.Date) v;
						pstm.setDate(index, new java.sql.Date(date.getTime()));
					} else {
						pstm.setObject(index, value.getValue());
					}
					
					index ++;
				}
			}
			
			if (!context.isPagedCountQuery()) {
				InterceptorContext.setPageQueryLimitParams(index, pstm);
			}
		}
		
		return invocation.proceed();
	}
	
	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
		
	}
}