// Path: src/main/java/com/slyak/util/AopTargetUtils.java
// public class AopTargetUtils {
// 
// 	/**
// 	 * 获取 目标对象
// 	 *
// 	 * @param proxy 代理对象
// 	 * @return 目标对象
// 	 */
// 	@SuppressWarnings("unchecked")
// 	public static <T> T getTarget(Object proxy) {
// 		if (Proxy.isProxyClass(proxy.getClass())) {
// 			return getJdkDynamicProxyTargetObject(proxy);
// 		}
// 		else if (ClassUtils.isCglibProxy(proxy)) {
// 			return getCglibProxyTargetObject(proxy);
// 		}
// 		else {
// 			return (T) proxy;
// 		}
// 	}
// 
// 	@SuppressWarnings("unchecked")
// 	private static <T> T getCglibProxyTargetObject(Object proxy) {
// 		try {
// 			Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
// 			h.setAccessible(true);
// 			Object dynamicAdvisedInterceptor = h.get(proxy);
// 			Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
// 			advised.setAccessible(true);
// 			return (T) (((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget());
// 		}
// 		catch (Exception e) {
// 			throw new RuntimeException(e);
// 		}
// 	}
// 
// 	@SuppressWarnings("unchecked")
// 	private static <T> T getJdkDynamicProxyTargetObject(Object proxy) {
// 		try {
// 			Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
// 			h.setAccessible(true);
// 			Object proxy_ = h.get(proxy);
// 			Field f = proxy_.getClass().getDeclaredField("target");
// 			f.setAccessible(true);
// 			return (T) f.get(proxy_);
// 		}
// 		catch (Exception e) {
// 			throw new RuntimeException(e);
// 		}
// 	}
// }


import com.slyak.util.AopTargetUtils;
import org.hibernate.query.NativeQuery;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.query.AbstractJpaQuery;
import org.springframework.data.jpa.repository.query.JpaParameters;
import org.springframework.data.jpa.repository.query.JpaQueryMethod;
import org.springframework.data.jpa.repository.query.QueryUtils;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.CollectionUtils;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
            Parameter parameter = parameters.getParameter(i);
            if (value != null && canBindParameter(parameter)) {
                if (!QueryBuilder.isValidValue(value)) {
                    continue;
                }
                Class<?> clz = value.getClass();
                if (clz.isPrimitive() || String.class.isAssignableFrom(clz) || Number.class.isAssignableFrom(clz)
                        || clz.isArray() || Collection.class.isAssignableFrom(clz) || clz.isEnum()) {
                    params.put(parameter.getName().orElse(null), value);
                } else {
                    params = QueryBuilder.toParams(value);
                }
            }
        }
        return params;
    }

    private Query createJpaQuery(String queryString) {
        Class<?> objectType = getQueryMethod().getReturnedObjectType();

        //get original proxy query.
        Query oriProxyQuery;

        //must be hibernate QueryImpl
        NativeQuery query;

        if (useJpaSpec && getQueryMethod().isQueryForEntity()) {
            oriProxyQuery = getEntityManager().createNativeQuery(queryString, objectType);
        } else {
            oriProxyQuery = getEntityManager().createNativeQuery(queryString);
// Path: src/main/java/com/slyak/util/AopTargetUtils.java
// public class AopTargetUtils {
// 
// 	/**
// 	 * 获取 目标对象
// 	 *
// 	 * @param proxy 代理对象
// 	 * @return 目标对象
// 	 */
// 	@SuppressWarnings("unchecked")
// 	public static <T> T getTarget(Object proxy) {
// 		if (Proxy.isProxyClass(proxy.getClass())) {
// 			return getJdkDynamicProxyTargetObject(proxy);
// 		}
// 		else if (ClassUtils.isCglibProxy(proxy)) {
// 			return getCglibProxyTargetObject(proxy);
// 		}
// 		else {
// 			return (T) proxy;
// 		}
// 	}
// 
// 	@SuppressWarnings("unchecked")
// 	private static <T> T getCglibProxyTargetObject(Object proxy) {
// 		try {
// 			Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
// 			h.setAccessible(true);
// 			Object dynamicAdvisedInterceptor = h.get(proxy);
// 			Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
// 			advised.setAccessible(true);
// 			return (T) (((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget());
// 		}
// 		catch (Exception e) {
// 			throw new RuntimeException(e);
// 		}
// 	}
// 
// 	@SuppressWarnings("unchecked")
// 	private static <T> T getJdkDynamicProxyTargetObject(Object proxy) {
// 		try {
// 			Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
// 			h.setAccessible(true);
// 			Object proxy_ = h.get(proxy);
// 			Field f = proxy_.getClass().getDeclaredField("target");
// 			f.setAccessible(true);
// 			return (T) f.get(proxy_);
// 		}
// 		catch (Exception e) {
// 			throw new RuntimeException(e);
// 		}
// 	}
// }


// Path: src/main/java/com/slyak/spring/jpa/FreemarkerTemplateQuery.java
import com.slyak.util.AopTargetUtils;
import org.hibernate.query.NativeQuery;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.query.AbstractJpaQuery;
import org.springframework.data.jpa.repository.query.JpaParameters;
import org.springframework.data.jpa.repository.query.JpaQueryMethod;
import org.springframework.data.jpa.repository.query.QueryUtils;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.CollectionUtils;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

            Parameter parameter = parameters.getParameter(i);
            if (value != null && canBindParameter(parameter)) {
                if (!QueryBuilder.isValidValue(value)) {
                    continue;
                }
                Class<?> clz = value.getClass();
                if (clz.isPrimitive() || String.class.isAssignableFrom(clz) || Number.class.isAssignableFrom(clz)
                        || clz.isArray() || Collection.class.isAssignableFrom(clz) || clz.isEnum()) {
                    params.put(parameter.getName().orElse(null), value);
                } else {
                    params = QueryBuilder.toParams(value);
                }
            }
        }
        return params;
    }

    private Query createJpaQuery(String queryString) {
        Class<?> objectType = getQueryMethod().getReturnedObjectType();

        //get original proxy query.
        Query oriProxyQuery;

        //must be hibernate QueryImpl
        NativeQuery query;

        if (useJpaSpec && getQueryMethod().isQueryForEntity()) {
            oriProxyQuery = getEntityManager().createNativeQuery(queryString, objectType);
        } else {
            oriProxyQuery = getEntityManager().createNativeQuery(queryString);
            query = AopTargetUtils.getTarget(oriProxyQuery);