org.onetwo.common.db.dquery.AbstractDynamicQueryHandler Maven / Gradle / Ivy
package org.onetwo.common.db.dquery;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.onetwo.common.convert.Types;
import org.onetwo.common.db.ParsedSqlContext;
import org.onetwo.common.db.dquery.annotation.SqlScript;
import org.onetwo.common.db.filequery.ParsedSqlUtils;
import org.onetwo.common.db.filequery.ParsedSqlUtils.ParsedSqlWrapper;
import org.onetwo.common.db.filequery.ParsedSqlUtils.ParsedSqlWrapper.SqlParamterMeta;
import org.onetwo.common.db.filequery.SimpleNamedQueryInfo;
import org.onetwo.common.db.spi.DynamicQueryHandler;
import org.onetwo.common.db.spi.NamedQueryInfo;
import org.onetwo.common.db.spi.QueryProvideManager;
import org.onetwo.common.db.spi.QueryWrapper;
import org.onetwo.common.db.spi.SqlParamterPostfixFunctionRegistry;
import org.onetwo.common.log.JFishLoggerFactory;
import org.onetwo.common.profiling.TimeCounter;
import org.onetwo.common.reflect.ReflectUtils;
import org.onetwo.common.spring.SpringUtils;
import org.onetwo.common.utils.CUtils;
import org.onetwo.common.utils.LangUtils;
import org.onetwo.common.utils.MathUtils;
import org.onetwo.common.utils.Page;
import org.onetwo.dbm.core.internal.AbstractDbmInterceptorChain.RepositoryDbmInterceptorChain;
import org.onetwo.dbm.core.spi.DbmInterceptor;
import org.onetwo.dbm.core.spi.DbmInterceptorChain;
import org.onetwo.dbm.exception.DbmException;
import org.onetwo.dbm.exception.FileNamedQueryException;
import org.onetwo.dbm.jdbc.spi.DbmJdbcOperations;
import org.slf4j.Logger;
import org.springframework.beans.BeanWrapper;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.util.Assert;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
abstract public class AbstractDynamicQueryHandler implements DynamicQueryHandler {
protected Logger logger = JFishLoggerFactory.getLogger(this.getClass());
private LoadingCache methodCache;
private QueryProvideManager em;
// private Object proxyObject;
private DbmJdbcOperations jdbcOperations;
final protected List> proxyInterfaces = new ArrayList>();
private MethodHandles.Lookup instanceForDefaultMethods;
public AbstractDynamicQueryHandler(QueryProvideManager em, LoadingCache methodCache, Class>... proxiedInterfaces){
this.em = em;
this.methodCache = methodCache;
// this.dbmJdbcOperations = em.getSessionFactory().getServiceRegistry().getDbmJdbcOperations();
this.jdbcOperations = em.getJdbcOperations();
this.proxyInterfaces.addAll(Arrays.asList(proxiedInterfaces));
Assert.notNull(jdbcOperations, "jdbcOperations can not be null");
}
/*private Optional getDbmEntityManager(){
if(DbmEntityManager.class.isInstance(em)){
return Optional.of((DbmEntityManager)em);
}
return Optional.empty();
}*/
final protected NamedQueryInfo getNamedQueryInfo(DynamicMethod dynamicMethod, Object[] parameterValues) {
String qname = getQueryName(dynamicMethod, parameterValues);
NamedQueryInfo queryInfo = this.em.getFileNamedQueryManager().getNamedSqlFileManager().getNamedQueryInfo(qname);
return queryInfo;
}
protected String getQueryName(DynamicMethod dynamicMethod, Object[] parameterValues) {
Object dispatcher = getQueryMatcherValue(dynamicMethod, parameterValues);
String queryName = dynamicMethod.getQueryName(parameterValues);
if(dispatcher!=null){
Assert.notNull(dispatcher, "dispatcher can not be null!");
return queryName + "(" + dispatcher+")";
}
return queryName;
}
private Object getQueryMatcherValue(DynamicMethod dynamicMethod, Object[] parameterValues){
return dynamicMethod.getMatcherValue(parameterValues);
}
// @Override
@Override
public Object invoke(Object proxyObj, Method method, Object[] args) {
Object proxy = getQueryObject();
if(Object.class == method.getDeclaringClass()) {
String name = method.getName();
if("equals".equals(name)) {
return proxy == args[0];
} else if("hashCode".equals(name)) {
return System.identityHashCode(proxy);
} else if("toString".equals(name)) {
return proxy.getClass().getName() + "@" +
Integer.toHexString(System.identityHashCode(proxy)) + ", InvocationHandler " + this;
} else {
throw new IllegalStateException(String.valueOf(method));
}
} else if(method.isDefault()) {
MethodHandles.Lookup lookup = this.instanceForDefaultMethods;
if (lookup==null) {
lookup = ReflectUtils.createMethodHandlesLookup(method.getDeclaringClass());
this.instanceForDefaultMethods = lookup;
}
Object result = ReflectUtils.invokeDefaultMethod(lookup, method, proxy, args);
return result;
}
DynamicMethod dmethod = getDynamicMethod(method);
// return invoke0(proxy, dmethod, args);
return invokeWithInterceptor(proxy, dmethod, args);
}
private Object invokeWithInterceptor(Object proxy, DynamicMethod dmethod, Object[] args){
MethodDynamicQueryInvokeContext invokeContext = createMethodInvokeContext(dmethod, args);
Collection interceptors = this.em.getRepositoryInterceptors();
if(interceptors.isEmpty()){
return invokeMethod(proxy, invokeContext);
}
DbmInterceptorChain chain = new RepositoryDbmInterceptorChain(proxy, invokeContext, interceptors, ()->invokeMethod(proxy, invokeContext));
return chain.invoke();
}
protected MethodDynamicQueryInvokeContext createMethodInvokeContext(DynamicMethod dmethod, Object[] args) {
MethodDynamicQueryInvokeContext invokeContext = null;
if (dmethod.getDynamicSqlTemplateParser()==null) {
NamedQueryInfo namedQueryInfo = getNamedQueryInfo(dmethod, args);
if(namedQueryInfo==null) {
String qname = getQueryName(dmethod, args);
throw new FileNamedQueryException("namedQuery not found : " + qname);
}
invokeContext = new MethodDynamicQueryInvokeContext(em, dmethod, args, namedQueryInfo);
invokeContext.setNamedQueryInfo(namedQueryInfo);
} else {
SimpleNamedQueryInfo namedQueryInfo = new SimpleNamedQueryInfo();
String queryName = dmethod.getQueryName(args);
namedQueryInfo.setName(queryName);
invokeContext = new MethodDynamicQueryInvokeContext(em, dmethod, args, namedQueryInfo);
}
return invokeContext;
}
private Object invokeMethod(Object proxy, MethodDynamicQueryInvokeContext invokeContext) {
try {
return this.dispatchInvoke(proxy, invokeContext);
}/* catch (HibernateException e) {
throw (HibernateException) e;
}*/
catch (FileNamedQueryException e) {
throw e;
}
catch (DbmException e) {
throw e;
}catch (Throwable e) {
String qname = invokeContext.getNamedQueryInfo().getFullName();
// throw new FileNamedQueryException("invoke query["+invokeContext.getQueryName()+"] error : " + e.getMessage(), e);
throw new FileNamedQueryException("invoke query["+qname+"] error : ", e);//.put("queryName", qname);
}
}
protected DynamicMethod getDynamicMethod(Method method){
try {
return methodCache.get(method);
} catch (ExecutionException e) {
throw new FileNamedQueryException("get dynamic method error: " + method.getName(), e);
// return newDynamicMethod(method);
} catch (UncheckedExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof DbmException) {
throw (DbmException) cause;
}
throw new FileNamedQueryException("get dynamic method error: " + method.getName(), cause);
// return newDynamicMethod(method);
}
}
@SuppressWarnings("unchecked")
public Object dispatchInvoke(Object proxy, MethodDynamicQueryInvokeContext invokeContext) throws Throwable {
DynamicMethod dmethod = invokeContext.getDynamicMethod();
Object[] args = invokeContext.getParameterValues();
Class> resultClass = dmethod.getResultClass(args);
// JFishNamedFileQueryInfo parsedQueryName = (JFishNamedFileQueryInfo) em.getFileNamedQueryManager().getNamedQueryInfo(invokeContext);
if(logger.isDebugEnabled()){
logger.debug("{}: {}", dmethod.getQueryName(args), LangUtils.toString(args));
}
Object result = null;
// Object[] methodArgs = null;
if(dmethod.isBatch()){
result = handleBatch(invokeContext);
} else if (dmethod.isScript()) {
ParsedSqlContext sv = em.getFileNamedQueryManager().parseNamedQuery(invokeContext);
String sql = sv.getParsedSql();
SqlScript sqlScript = dmethod.getSqlScript();
Resource sqlRes = new ByteArrayResource(sql.getBytes(sqlScript.sqlScriptEncoding()));
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(sqlScript.isContinueOnError());
populator.setSeparator(sqlScript.separator());
populator.setSqlScriptEncoding(sqlScript.sqlScriptEncoding());
populator.addScript(sqlRes);
DatabasePopulatorUtils.execute(populator, em.getDataSource());
} else if (dmethod.isExecuteUpdate()){
QueryWrapper dq = em.getFileNamedQueryManager().createQuery(invokeContext);
result = dq.executeUpdate();
} else if (dmethod.hasPageParamter()){
Page> page = dmethod.getPageParamter(args);
// DbmNamedFileQueryFactory#findPage
Page> resultPage = em.getFileNamedQueryManager().findPage(page, invokeContext);
result = convertPageByResultType(resultPage, resultClass);
} else if (dmethod.getPageParamter(args)!=null) {
// 通过是否能获取page参数再次判断是否分页查询
Page> page = dmethod.getPageParamter(args);
// DbmNamedFileQueryFactory#findPage
Page> resultPage = em.getFileNamedQueryManager().findPage(page, invokeContext);
result = convertPageByResultType(resultPage, resultClass);
} else if (Collection.class.isAssignableFrom(resultClass)){
List> datalist = em.getFileNamedQueryManager().findList(invokeContext);
if (resultClass.isAssignableFrom(datalist.getClass())){
result = datalist;
} else {
Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy