/* * Copyright 2014 mango.jfaster.org * * The Mango Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package org.jfaster.mango.operator; import org.jfaster.mango.annotation.UseMaster; import org.jfaster.mango.binding.DefaultParameterContext; import org.jfaster.mango.binding.InvocationContextFactory; import org.jfaster.mango.binding.ParameterContext; import org.jfaster.mango.datasource.DataSourceFactoryGroup; import org.jfaster.mango.datasource.DataSourceType; import org.jfaster.mango.descriptor.MethodDescriptor; import static org.jfaster.mango.descriptor.MethodDescriptors.*; import org.jfaster.mango.descriptor.ParameterDescriptor; import org.jfaster.mango.interceptor.InterceptorChain; import org.jfaster.mango.interceptor.InvocationInterceptorChain; import org.jfaster.mango.jdbc.JdbcOperations; import org.jfaster.mango.jdbc.JdbcTemplate; import org.jfaster.mango.operator.cache.*; import org.jfaster.mango.operator.generator.DataSourceGenerator; import org.jfaster.mango.operator.generator.DataSourceGeneratorFactory; import org.jfaster.mango.operator.generator.TableGenerator; import org.jfaster.mango.operator.generator.TableGeneratorFactory; import org.jfaster.mango.parser.ASTRootNode; import org.jfaster.mango.parser.SqlParser; import org.jfaster.mango.stat.MetaStat; import org.jfaster.mango.util.jdbc.OperatorType; import org.jfaster.mango.util.jdbc.SQLType; import java.util.ArrayList; import java.util.List; /** * @author ash */ public class OperatorFactory { private final CacheHandler cacheHandler; private final InterceptorChain interceptorChain; private final JdbcOperations jdbcOperations; private final Config config; private final TableGeneratorFactory tableGeneratorFactory; private final DataSourceGeneratorFactory dataSourceGeneratorFactory; public OperatorFactory(DataSourceFactoryGroup dataSourceFactoryGroup, CacheHandler cacheHandler, InterceptorChain interceptorChain, Config config) { this.cacheHandler = cacheHandler; this.interceptorChain = interceptorChain; this.config = config; this.jdbcOperations = new JdbcTemplate(); this.tableGeneratorFactory = new TableGeneratorFactory(); this.dataSourceGeneratorFactory = new DataSourceGeneratorFactory(dataSourceFactoryGroup); } public Operator getOperator(MethodDescriptor md, MetaStat stat) { ASTRootNode rootNode = SqlParser.parse(getSQL(md)).init(); // 初始化抽象语法树 List<ParameterDescriptor> pds = md.getParameterDescriptors(); // 方法参数描述 OperatorType operatorType = getOperatorType(pds, rootNode); stat.setOperatorType(operatorType); if (operatorType == OperatorType.BATCHUPDATE) { // 批量更新重新组装ParameterDescriptorList ParameterDescriptor pd = pds.get(0); pds = new ArrayList<ParameterDescriptor>(1); pds.add(ParameterDescriptor.create(0, pd.getMappedClass(), pd.getAnnotations(), pd.getName())); } ParameterContext context = DefaultParameterContext.create(pds); rootNode.expandParameter(context); // 扩展简化的参数节点 rootNode.checkAndBind(context); // 检查类型,设定参数绑定器 // 构造表生成器 boolean isSqlUseGlobalTable = !rootNode.getASTGlobalTables().isEmpty(); TableGenerator tableGenerator = tableGeneratorFactory.getTableGenerator( getShardingAnno(md), getGlobalTable(md), isSqlUseGlobalTable, context); // 构造数据源生成器 DataSourceType dataSourceType = getDataSourceType(operatorType, md); DataSourceGenerator dataSourceGenerator = dataSourceGeneratorFactory. getDataSourceGenerator(dataSourceType, getShardingAnno(md), getDataSourceFactoryName(md), context); Operator operator; if (isUseCache(md)) { CacheDriver driver = new CacheDriver(md, rootNode, cacheHandler, context); stat.setCacheable(true); stat.setUseMultipleKeys(driver.isUseMultipleKeys()); stat.setCacheNullObject(driver.isCacheNullObject()); switch (operatorType) { case QUERY: operator = new CacheableQueryOperator(rootNode, md, driver, config); break; case UPDATE: operator = new CacheableUpdateOperator(rootNode, md, driver, config); break; case BATCHUPDATE: operator = new CacheableBatchUpdateOperator(rootNode, md, driver, config); break; default: throw new IllegalStateException(); } } else { switch (operatorType) { case QUERY: operator = new QueryOperator(rootNode, md, config); break; case UPDATE: operator = new UpdateOperator(rootNode, md, config); break; case BATCHUPDATE: operator = new BatchUpdateOperator(rootNode, md, config); break; default: throw new IllegalStateException(); } } InvocationInterceptorChain chain = new InvocationInterceptorChain(interceptorChain, pds, rootNode.getSQLType()); operator.setTableGenerator(tableGenerator); operator.setDataSourceGenerator(dataSourceGenerator); operator.setInvocationContextFactory(InvocationContextFactory.create(context)); operator.setInvocationInterceptorChain(chain); operator.setJdbcOperations(jdbcOperations); return operator; } OperatorType getOperatorType(List<ParameterDescriptor> pds, ASTRootNode rootNode) { OperatorType operatorType; if (rootNode.getSQLType() == SQLType.SELECT) { operatorType = OperatorType.QUERY; } else { operatorType = OperatorType.UPDATE; if (pds.size() == 1) { // 只有一个参数 ParameterDescriptor pd = pds.get(0); if (pd.isIterable() && rootNode.getJDBCIterableParameters().isEmpty()) { // 参数可迭代,同时sql中没有in语句 operatorType = OperatorType.BATCHUPDATE; } } } return operatorType; } DataSourceType getDataSourceType(OperatorType operatorType, MethodDescriptor md) { DataSourceType dataSourceType = DataSourceType.SLAVE; if (operatorType != OperatorType.QUERY || md.isAnnotationPresent(UseMaster.class)) { dataSourceType = DataSourceType.MASTER; } return dataSourceType; } }