diff --git a/choerodon-gitlab4j-api/pom.xml b/choerodon-gitlab4j-api/pom.xml index 3b42a939..16a7aa42 100644 --- a/choerodon-gitlab4j-api/pom.xml +++ b/choerodon-gitlab4j-api/pom.xml @@ -4,7 +4,7 @@ 4.0.0 choerodon-gitlab4j-api - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT jar choerodon-gitlab4j-api GitLab API Java Client @@ -21,7 +21,7 @@ io.choerodon choerodon-starter-parent - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT package diff --git a/choerodon-gitlab4j-api/src/main/java/org/gitlab4j/api/RepositoryApi.java b/choerodon-gitlab4j-api/src/main/java/org/gitlab4j/api/RepositoryApi.java index 5dcb8c2d..61e1e96e 100644 --- a/choerodon-gitlab4j-api/src/main/java/org/gitlab4j/api/RepositoryApi.java +++ b/choerodon-gitlab4j-api/src/main/java/org/gitlab4j/api/RepositoryApi.java @@ -464,7 +464,7 @@ public InputStream getRawBlobContent(Integer projectId, String sha) throws GitLa */ public InputStream getRepositoryArchive(Integer projectId, String sha) throws GitLabApiException { Form formData = new GitLabApiForm().withParam("sha", sha); - Response response = getWithAccepts(Response.Status.OK, formData.asMap(), MediaType.MEDIA_TYPE_WILDCARD, + Response response = getWithAccepts(Response.Status.OK, formData.asMap(), MediaType.WILDCARD, "projects", projectId, "repository", "archive"); return (response.readEntity(InputStream.class)); } diff --git a/choerodon-starter-asgard/pom.xml b/choerodon-starter-asgard/pom.xml index 1d79864f..a6e4e385 100644 --- a/choerodon-starter-asgard/pom.xml +++ b/choerodon-starter-asgard/pom.xml @@ -5,12 +5,11 @@ choerodon-starter-parent io.choerodon - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT 4.0.0 choerodon-starter-asgard - 2.0.0.RELEASE @@ -50,4 +49,4 @@ - \ No newline at end of file + diff --git a/choerodon-starter-asgard/src/main/java/io/choerodon/asgard/schedule/ScheduleConsumer.java b/choerodon-starter-asgard/src/main/java/io/choerodon/asgard/schedule/ScheduleConsumer.java index 556540de..302fa5a9 100644 --- a/choerodon-starter-asgard/src/main/java/io/choerodon/asgard/schedule/ScheduleConsumer.java +++ b/choerodon-starter-asgard/src/main/java/io/choerodon/asgard/schedule/ScheduleConsumer.java @@ -1,21 +1,7 @@ package io.choerodon.asgard.schedule; -import com.fasterxml.jackson.core.type.TypeReference; - -import io.choerodon.asgard.common.AbstractAsgardConsumer; -import io.choerodon.asgard.common.ApplicationContextHelper; -import io.choerodon.asgard.common.UpdateStatusDTO; -import io.choerodon.asgard.schedule.annotation.JobTask; -import io.choerodon.asgard.schedule.dto.PollScheduleInstanceDTO; -import io.choerodon.asgard.schedule.dto.ScheduleInstanceConsumerDTO; -import io.choerodon.asgard.schedule.feign.ScheduleConsumerClient; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionStatus; -import org.springframework.util.StringUtils; +import static io.choerodon.asgard.common.InstanceResultUtils.*; import java.io.IOException; import java.util.HashMap; @@ -26,9 +12,20 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; -import static io.choerodon.asgard.common.InstanceResultUtils.getErrorInfoFromException; -import static io.choerodon.asgard.common.InstanceResultUtils.getLoggerException; -import static io.choerodon.asgard.common.InstanceResultUtils.resultToJson; +import com.fasterxml.jackson.core.type.TypeReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.util.StringUtils; + +import io.choerodon.asgard.common.AbstractAsgardConsumer; +import io.choerodon.asgard.common.ApplicationContextHelper; +import io.choerodon.asgard.common.UpdateStatusDTO; +import io.choerodon.asgard.schedule.annotation.JobTask; +import io.choerodon.asgard.schedule.dto.PollScheduleInstanceDTO; +import io.choerodon.asgard.schedule.dto.ScheduleInstanceConsumerDTO; +import io.choerodon.asgard.schedule.feign.ScheduleConsumerClient; public class ScheduleConsumer extends AbstractAsgardConsumer { @@ -72,6 +69,17 @@ protected void scheduleRunning(String instance) { } private ScheduleInstanceConsumerDTO invoke(final ScheduleInstanceConsumerDTO data) { + final JobTaskInvokeBean invokeBean = invokeBeanMap.get(data.getMethod()); + final JobTask jobTask = invokeBean.jobTask; + if (jobTask.enableTransaction()) { + return invokeWithinTransaction(data); + } else { + return invokeWithoutTransaction(data); + } + + } + + private ScheduleInstanceConsumerDTO invokeWithinTransaction(final ScheduleInstanceConsumerDTO data) { final JobTaskInvokeBean invokeBean = invokeBeanMap.get(data.getMethod()); final JobTask jobTask = invokeBean.jobTask; PlatformTransactionManager platformTransactionManager = getSagaTaskTransactionManager(jobTask.transactionManager()); @@ -97,6 +105,29 @@ private ScheduleInstanceConsumerDTO invoke(final ScheduleInstanceConsumerDTO dat return data; } + private ScheduleInstanceConsumerDTO invokeWithoutTransaction(final ScheduleInstanceConsumerDTO data) { + final JobTaskInvokeBean invokeBean = invokeBeanMap.get(data.getMethod()); + beforeInvoke(data.getUserDetails()); + try { + invokeBean.method.setAccessible(true); + Object result = invokeBean.method.invoke(invokeBean.object, getInputMap(data.getExecuteParams())); + if (result != null) { + result = objectMapper.writeValueAsString(result); + } + scheduleConsumerClient.updateStatus(data.getId(), new UpdateStatusDTO(data.getId(), QuartzDefinition.InstanceStatus.COMPLETED.name(), + resultToJson(result, objectMapper), null, data.getObjectVersionNumber())); + runningTasks.remove(data.getId()); + } catch (Exception e) { + String errorMsg = getErrorInfoFromException(e); + LOGGER.info("@JobTask method: {}, id: {} invoke error", data.getMethod(), data.getId(), getLoggerException(e)); + invokeError(data, errorMsg); + } finally { + afterInvoke(); + } + return data; + } + + private void invokeError(final PlatformTransactionManager platformTransactionManager, final TransactionStatus status, final ScheduleInstanceConsumerDTO data, @@ -106,14 +137,19 @@ private void invokeError(final PlatformTransactionManager platformTransactionMan } catch (Exception e) { LOGGER.warn("@JobTask method: {}, id: {} transaction rollback error", data.getMethod(), data.getId(), e); } finally { - try { - scheduleConsumerClient.updateStatus(data.getId(), new UpdateStatusDTO(data.getId(), - QuartzDefinition.InstanceStatus.FAILED.name(), null, errorMsg, data.getObjectVersionNumber())); - runningTasks.remove(data.getId()); - } catch (Exception ex) { - LOGGER.warn("@JobTask method: {}, id: {} updateStatusFailed error, error message: {}", data.getMethod(), data.getId(), ex.getMessage()); - runningTasks.remove(data.getId()); - } + invokeError(data, errorMsg); + } + } + + private void invokeError(final ScheduleInstanceConsumerDTO data, + final String errorMsg) { + try { + scheduleConsumerClient.updateStatus(data.getId(), new UpdateStatusDTO(data.getId(), + QuartzDefinition.InstanceStatus.FAILED.name(), null, errorMsg, data.getObjectVersionNumber())); + runningTasks.remove(data.getId()); + } catch (Exception ex) { + LOGGER.warn("@JobTask method: {}, id: {} updateStatusFailed error, error message: {}", data.getMethod(), data.getId(), ex.getMessage()); + runningTasks.remove(data.getId()); } } diff --git a/choerodon-starter-asgard/src/main/java/io/choerodon/asgard/schedule/annotation/JobTask.java b/choerodon-starter-asgard/src/main/java/io/choerodon/asgard/schedule/annotation/JobTask.java index a0a69463..a349b0ca 100644 --- a/choerodon-starter-asgard/src/main/java/io/choerodon/asgard/schedule/annotation/JobTask.java +++ b/choerodon-starter-asgard/src/main/java/io/choerodon/asgard/schedule/annotation/JobTask.java @@ -5,10 +5,10 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import io.choerodon.core.iam.ResourceLevel; - import org.springframework.transaction.annotation.Isolation; +import io.choerodon.core.iam.ResourceLevel; + @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface JobTask { @@ -41,6 +41,13 @@ */ boolean transactionReadOnly() default false; + /** + * 是否开启事务 + * + * @return 是否开启事务 + */ + boolean enableTransaction() default true; + /** * 事务的隔离级别 * diff --git a/choerodon-starter-core/pom.xml b/choerodon-starter-core/pom.xml index aa784d11..be99a099 100644 --- a/choerodon-starter-core/pom.xml +++ b/choerodon-starter-core/pom.xml @@ -5,16 +5,18 @@ choerodon-starter-parent io.choerodon - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT 4.0.0 choerodon-starter-core + org.hzero.starter hzero-starter-mybatis-mapper + 1.8.1.RELEASE org.hzero.boot @@ -23,4 +25,4 @@ - \ No newline at end of file + diff --git a/choerodon-starter-core/src/main/java/io/choerodon/core/utils/FeignFallbackUtil.java b/choerodon-starter-core/src/main/java/io/choerodon/core/utils/FeignFallbackUtil.java new file mode 100644 index 00000000..f702efe9 --- /dev/null +++ b/choerodon-starter-core/src/main/java/io/choerodon/core/utils/FeignFallbackUtil.java @@ -0,0 +1,39 @@ +package io.choerodon.core.utils; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.Arrays; + +import com.alibaba.fastjson.JSON; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.Assert; + +/** + * Copyright (c) 2022. Hand Enterprise Solution Company. All right reserved. + * + * @author zongqi.hao@zknow.com + * @since 2022/7/13 + */ +public class FeignFallbackUtil { + + private FeignFallbackUtil() { + } + + public static T get(Throwable cause, Class targetClass) { + Assert.notNull(targetClass, "feign target class could not be null!"); + Logger logger = LoggerFactory.getLogger(targetClass); + InvocationHandler invocationHandler = (proxy, method, args) -> { + logger.error("error when call {}.{} by params{}", method.getDeclaringClass().getSimpleName(), + method.getName(), JSON.toJSONString(args)); + if (cause != null) { + logger.error(cause.getMessage(), cause); + } + return ResponseEntity.badRequest().contentType(MediaType.APPLICATION_JSON).body("请联系运维人员"); + }; + return (T) Proxy.newProxyInstance(targetClass.getClassLoader(), new Class[]{targetClass}, invocationHandler); + } + +} diff --git a/choerodon-starter-core/src/main/java/io/choerodon/core/utils/TypeUtils.java b/choerodon-starter-core/src/main/java/io/choerodon/core/utils/TypeUtils.java new file mode 100644 index 00000000..63c24122 --- /dev/null +++ b/choerodon-starter-core/src/main/java/io/choerodon/core/utils/TypeUtils.java @@ -0,0 +1,99 @@ +package io.choerodon.core.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by younger on 2018/3/29. + */ +public class TypeUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(TypeUtils.class); + public static final String SEARCH_PARAM = "searchParam"; + public static final String PARAMS = "params"; + + private TypeUtils() { + } + + /** + * obj转string类型 + */ + + public static String objToString(Object obj) { + if (obj == null) { + return null; + } + return String.valueOf(obj); + } + + /** + * obj转integer类型 + */ + + public static Integer objToInteger(Object obj) { + if (obj == null || "".equals(obj)) { + return null; + } + return Integer.valueOf(String.valueOf(obj)); + } + + /** + * obj转long类型 + */ + + public static Long objToLong(Object obj) { + if (obj == null || "".equals(obj)) { + return null; + } + return Long.valueOf(String.valueOf(obj)); + } + + /** + * obj转double类型 + */ + + public static double objTodouble(Object obj) { + if (obj == null || "".equals(obj)) { + return 0; + } + return Double.parseDouble(String.valueOf(obj)); + } + + /** + * obj转int类型 + */ + + public static int objToInt(Object obj) { + if (obj == null || "".equals(obj)) { + return 0; + } + return Integer.parseInt(String.valueOf(obj)); + } + + /** + * obj转boolean类型 + */ + + public static Boolean objToBoolean(Object obj) { + if (obj == null || "".equals(obj)) { + return false; + } + return Boolean.valueOf(String.valueOf(obj)); + } + + /** + * 对象转换 + * + * @param obj obj + * @param t + * @return t + */ + public static T cast(Object obj) { + if (obj == null) { + return null; + } else { + return (T) obj; + } + } + +} diff --git a/choerodon-starter-core/src/main/java/io/choerodon/mybatis/pagehelper/PageInterceptor.java b/choerodon-starter-core/src/main/java/io/choerodon/mybatis/pagehelper/PageInterceptor.java new file mode 100644 index 00000000..2a5593d4 --- /dev/null +++ b/choerodon-starter-core/src/main/java/io/choerodon/mybatis/pagehelper/PageInterceptor.java @@ -0,0 +1,344 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 abel533@gmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package io.choerodon.mybatis.pagehelper; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.choerodon.core.domain.PageInfo; +import io.choerodon.mybatis.pagehelper.cache.Cache; +import io.choerodon.mybatis.pagehelper.cache.CacheFactory; +import io.choerodon.mybatis.pagehelper.domain.Sort; +import io.choerodon.mybatis.pagehelper.exception.PageException; +import io.choerodon.mybatis.pagehelper.page.PageCountCacher; +import io.choerodon.mybatis.pagehelper.page.PageMethod; +import io.choerodon.mybatis.pagehelper.parser.IOrderByParser; +import io.choerodon.mybatis.pagehelper.util.MappedStatementUtils; + + +/** + * todo scp 临时覆盖分页缓存内存不释放问题 + * Mybatis - 通用分页拦截器 + * 项目地址 : http://git.oschina.net/free/Mybatis_PageHelper + * + * @author liuzh/abel533/isea533 + * @version 5.0.0 + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +@InterceptorOrder(0) +@Intercepts( + { + @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), + @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}), + } +) +public class PageInterceptor implements Interceptor { + private static final String CUSTOM_COUNT_SQL_POSTFIX = "_COUNT"; + /** + * 缓存count查询的ms + **/ + private Cache msCountMap = null; + private Dialect dialect = null; + private IOrderByParser orderByParser; + private Field additionalParametersField; + private final PageCountCacher pageCountCacher; + + private static final Logger logger = LoggerFactory.getLogger(PageInterceptor.class); + + public PageInterceptor(Dialect dialect, IOrderByParser orderByParser, PageCountCacher pageCountCacher) { + this.dialect = dialect; + this.orderByParser = orderByParser; + this.pageCountCacher = pageCountCacher; + } + + public PageInterceptor(Dialect dialect, Field additionalParametersField, Cache msCountMap, PageCountCacher pageCountCacher) { + this.dialect = dialect; + this.additionalParametersField = additionalParametersField; + this.msCountMap = msCountMap; + this.pageCountCacher = pageCountCacher; + } + + @Override + public Object intercept(Invocation invocation) throws Throwable { + try { + Object[] args = invocation.getArgs(); + MappedStatement ms = (MappedStatement) args[0]; + Object parameter = args[1]; + RowBounds rowBounds = (RowBounds) args[2]; + ResultHandler resultHandler = (ResultHandler) args[3]; + Executor executor = (Executor) invocation.getTarget(); + CacheKey cacheKey; + BoundSql boundSql; + //由于逻辑关系,只会进入一次 + if (args.length == 4) { + //4 个参数时 + boundSql = ms.getBoundSql(parameter); + cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql); + } else { + //6 个参数时 + cacheKey = (CacheKey) args[4]; + boundSql = (BoundSql) args[5]; + } + List resultList; + BoundSql sqlWithOrderBy = null; + boolean executePage = !dialect.skip(ms, parameter, rowBounds); + //获得ThreadLocal里面的sort参数 + Sort sort = PageHelper.getLocalSort(); + boolean executeSort = (sort != null); + //反射获取动态参数 + Map additionalParameters = (Map) additionalParametersField.get(boundSql); + if (executePage && !executeSort) { + //只分页,count统计sql + if (doCount(ms, parameter, rowBounds, resultHandler, executor, boundSql, additionalParameters)) { + return dialect.afterPage(new ArrayList(), parameter, rowBounds); + } + //判断是否需要进行分页查询 + DoPage doPage = + new DoPage(ms, parameter, rowBounds, resultHandler, + executor, cacheKey, boundSql, sqlWithOrderBy, additionalParameters).invoke(); + resultList = doPage.getResultList(); + parameter = doPage.getParameter(); + return dialect.afterPage(resultList, parameter, rowBounds); + } else if (!executePage && executeSort) { + //只排序 + parameter = dialect.processParameterObject(ms, parameter, boundSql, cacheKey); + //拼接排序order by操作 + sqlWithOrderBy = doSort(ms, parameter, boundSql, sqlWithOrderBy, sort, executeSort); + //设置动态参数 + setDynamicParam(sqlWithOrderBy, additionalParameters); + //执行排序查询 + return executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, sqlWithOrderBy); + } else if (executePage && executeSort) { + //分页和排序 + if (doCount(ms, parameter, rowBounds, resultHandler, executor, boundSql, additionalParameters)) { + return dialect.afterPage(new ArrayList(), parameter, rowBounds); + } + //拼接排序order by操作 + sqlWithOrderBy = doSort(ms, parameter, boundSql, sqlWithOrderBy, sort, executeSort); + //判断是否需要进行分页查询 + DoPage doPage = + new DoPage(ms, parameter, rowBounds, resultHandler, executor, + cacheKey, boundSql, sqlWithOrderBy, additionalParameters).invoke(); + resultList = doPage.getResultList(); + parameter = doPage.getParameter(); + return dialect.afterPage(resultList, parameter, rowBounds); + } else { + //即不分页也不排序 + //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页 + return executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql); + } + } finally { + dialect.afterAll(); + } + } + + @Override + public Object plugin(Object target) { + return Plugin.wrap(target, this); + } + + @Override + public void setProperties(Properties properties) { + dialect.setProperties(properties); + msCountMap = CacheFactory.createCache(properties.getProperty("msCountCache"), "ms", properties); + try { + additionalParametersField = BoundSql.class.getDeclaredField("additionalParameters"); + additionalParametersField.setAccessible(true); + } catch (NoSuchFieldException e) { + logger.debug("NoSuchFieldException:" + e); + } + } + + private class DoPage { + private MappedStatement ms; + private Object parameter; + private RowBounds rowBounds; + private ResultHandler resultHandler; + private Executor executor; + private CacheKey cacheKey; + private BoundSql boundSql; + private BoundSql sqlWithOrderBy; + private Map additionalParameters; + private List resultList; + + public DoPage(MappedStatement ms, Object parameter, RowBounds rowBounds, + ResultHandler resultHandler, Executor executor, CacheKey cacheKey, + BoundSql boundSql, BoundSql sqlWithOrderBy, Map additionalParameters) { + this.ms = ms; + this.parameter = parameter; + this.rowBounds = rowBounds; + this.resultHandler = resultHandler; + this.executor = executor; + this.cacheKey = cacheKey; + this.boundSql = boundSql; + this.sqlWithOrderBy = sqlWithOrderBy; + this.additionalParameters = additionalParameters; + } + + public Object getParameter() { + return parameter; + } + + public List getResultList() { + return resultList; + } + + public DoPage invoke() throws java.sql.SQLException { + if (dialect.beforePage(ms, parameter, rowBounds)) { + //生成分页的缓存 key + CacheKey pageKey = cacheKey; + //处理参数对象 + parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey); + //调用方言获取分页 sql + String pageSql; + if (sqlWithOrderBy != null) { + pageSql = dialect.getPageSql(ms, sqlWithOrderBy, parameter, rowBounds, pageKey); + } else { + pageSql = dialect.getPageSql(ms, boundSql, parameter, rowBounds, pageKey); + } + BoundSql pageBoundSql = + new BoundSql(ms.getConfiguration(), pageSql, boundSql.getParameterMappings(), parameter); + setDynamicParam(pageBoundSql, additionalParameters); + //执行分页查询 + resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql); + } else { + if (sqlWithOrderBy != null) { + setDynamicParam(sqlWithOrderBy, additionalParameters); + resultList = + executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, sqlWithOrderBy); + } else { + setDynamicParam(boundSql, additionalParameters); + resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql); + } + } + return this; + } + } + + private void setDynamicParam(BoundSql boundSql, Map additionalParameters) { + for (Map.Entry entry : additionalParameters.entrySet()) { + boundSql.setAdditionalParameter(entry.getKey(), entry.getValue()); + } + } + + private BoundSql doSort(MappedStatement ms, Object parameter, BoundSql boundSql, + BoundSql sqlWithOrderBy, Sort sort, boolean executeSort) { + if (executeSort) { + //拼接order by并不会影响count查询,这里不对count查询的sql拼接order by + //转换sort对象为sql字符串 + String orderBySql = orderByParser.sortToString(sort, ms); + String sql = boundSql.getSql(); + if (orderByParser.containOrderBy(sql)) { + throw new PageException("the select sql can not contains order by while using doPageAndSort or doSort"); + } + sql = sql + " order by " + orderBySql; + sqlWithOrderBy = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), parameter); + } + return sqlWithOrderBy; + } + + private boolean doCount(MappedStatement ms, Object parameter, RowBounds rowBounds, + ResultHandler resultHandler, Executor executor, BoundSql boundSql, + Map additionalParameters) throws Exception { + //判断是否需要进行 count 查询 + if (dialect.beforeCount(ms, parameter, rowBounds)) { + // 若已经指定了total,跳过countSql执行 + PageInfo pageInfo = PageMethod.getLocalPage(); + if (pageInfo != null && pageInfo.getTotal() > 0) { + //处理查询总数 + long count = pageInfo.getTotal(); + //返回 true 时继续分页查询,false 时直接返回 + if (!dialect.afterCount(count, parameter, rowBounds)) { + //当查询总数为 0 时,直接返回空的结果 + return true; + } + return false; + } + + MappedStatement customCountMs = null; + try { + customCountMs = ms.getConfiguration().getMappedStatement(ms.getId() + CUSTOM_COUNT_SQL_POSTFIX); + } catch (Exception e) { + //ignore + } + + Long count; + if (customCountMs != null) { + // 如果已经缓存查询总数,则使用缓存值 + MappedStatement countMs = customCountMs; + count = pageCountCacher.getCount(countMs.getId(), pageInfo, (k) -> { + //自定义Count SQL + Object countResultList = executor.query(countMs, parameter, RowBounds.DEFAULT, resultHandler); + return (Long) ((List) countResultList).get(0); + }); + } else { + //自动生成Count SQL + CacheKey countKey = executor.createCacheKey(ms, parameter, RowBounds.DEFAULT, boundSql); + countKey.update(MappedStatementUtils.COUNT); + MappedStatement countMs = msCountMap.get(countKey); + if (countMs == null) { + //根据当前的 ms 创建一个返回值为 Long 类型的 ms + countMs = MappedStatementUtils.newCountMappedStatement(ms); + // todo 唯一覆盖 + msCountMap.put(countKey.clone(), countMs); + } + //调用方言获取 count sql + String countSql = dialect.getCountSql(ms, boundSql, parameter, rowBounds, countKey); + BoundSql countBoundSql = + new BoundSql(ms.getConfiguration(), countSql, boundSql.getParameterMappings(), parameter); + //当使用动态 SQL 时,可能会产生临时的参数,这些参数需要手动设置到新的 BoundSql 中 + setDynamicParam(countBoundSql, additionalParameters); + MappedStatement finalCountMs = countMs; + count = pageCountCacher.getCount(countMs.getId(), parameter, (k) -> { + //执行 count 查询 + Object countResultList = executor.query(finalCountMs, parameter, RowBounds.DEFAULT, resultHandler, countKey, countBoundSql); + return (Long) ((List) countResultList).get(0); + }); + } + + //处理查询总数 + //返回 true 时继续分页查询,false 时直接返回 + if (!dialect.afterCount(count, parameter, rowBounds)) { + //当查询总数为 0 时,直接返回空的结果 + return true; + } + } + return false; + } +} diff --git a/choerodon-starter-fragment/pom.xml b/choerodon-starter-fragment/pom.xml index 77f5ddce..67b1bd55 100644 --- a/choerodon-starter-fragment/pom.xml +++ b/choerodon-starter-fragment/pom.xml @@ -5,7 +5,7 @@ choerodon-starter-parent io.choerodon - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT 4.0.0 @@ -23,4 +23,4 @@ hzero-starter-core - \ No newline at end of file + diff --git a/choerodon-starter-limit/pom.xml b/choerodon-starter-limit/pom.xml index e7a88c25..75870a93 100644 --- a/choerodon-starter-limit/pom.xml +++ b/choerodon-starter-limit/pom.xml @@ -4,7 +4,7 @@ choerodon-starter-parent io.choerodon - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT 4.0.0 diff --git a/choerodon-starter-nacos-client/pom.xml b/choerodon-starter-nacos-client/pom.xml index e47ecbb0..c0ff8196 100644 --- a/choerodon-starter-nacos-client/pom.xml +++ b/choerodon-starter-nacos-client/pom.xml @@ -19,7 +19,7 @@ choerodon-starter-parent io.choerodon - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT 4.0.0 @@ -39,7 +39,7 @@ 2.12.2 3.5.0 1.7.30 - 1.2.3 + 1.2.9 diff --git a/choerodon-starter-only-office/pom.xml b/choerodon-starter-only-office/pom.xml index 4a43f500..2c465ef2 100644 --- a/choerodon-starter-only-office/pom.xml +++ b/choerodon-starter-only-office/pom.xml @@ -5,12 +5,12 @@ choerodon-starter-parent io.choerodon - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT 4.0.0 choerodon-starter-only-office - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT @@ -53,4 +53,4 @@ - \ No newline at end of file + diff --git a/choerodon-tool-liquibase/pom.xml b/choerodon-tool-liquibase/pom.xml index 36dfcbf0..f4958f4e 100644 --- a/choerodon-tool-liquibase/pom.xml +++ b/choerodon-tool-liquibase/pom.xml @@ -5,7 +5,7 @@ io.choerodon choerodon-starter-parent - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT choerodon-tool-liquibase diff --git a/pom.xml b/pom.xml index 2762ece1..9b6785e0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,16 +6,15 @@ io.choerodon choerodon-starter-parent - 2.0.0.RELEASE + 2.2.0-19-SNAPSHOT pom - org.hzero - hzero-parent - 1.8.3.RELEASE + org.hzero.starter + hzero-starter-parent + 1.8.0.RELEASE - UTF-8 1.8