Search in sources :

Example 1 with SqlMetadata

use of com.mendmix.mybatis.metadata.SqlMetadata in project jeesuite-libs by vakinge.

the class CacheHandler method removeCacheByDyncQuery.

/**
 * 根据动态查询内容清理缓存
 * @param sqlMetadata 查询主键列表SQL语句信息
 * @param parameter 参数
 * @throws Exception
 */
private void removeCacheByDyncQuery(MapperMetadata mapperMeta, BoundSql boundSql, SqlMetadata sqlMetadata) {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet rs = null;
    try {
        parseDyncQueryParameters(boundSql, sqlMetadata);
        connection = dataSource.getConnection();
        statement = connection.prepareStatement(sqlMetadata.getSql());
        List<Object> parameters = sqlMetadata.getParameters();
        for (int i = 0; i < parameters.size(); i++) {
            statement.setObject(i + 1, parameters.get(i));
        }
        rs = statement.executeQuery();
        List<String> ids = new ArrayList<>();
        while (rs.next()) {
            ids.add(rs.getString(1));
        }
        if (ids != null && !ids.isEmpty()) {
            List<String> idCacheKeys = ids.stream().map(id -> {
                return mapperMeta.getEntityClass().getSimpleName() + ID_CACHEKEY_JOIN + id.toString();
            }).collect(Collectors.toList());
            CacheUtils.remove(idCacheKeys.toArray(new String[0]));
            if (logger.isDebugEnabled()) {
                logger.debug("remove cacheKeys:{}", idCacheKeys);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        final String groupName = mapperMeta.getEntityClass().getSimpleName();
        clearCacheGroup(groupName);
    } finally {
        try {
            rs.close();
        } catch (Exception e2) {
        }
        try {
            statement.close();
        } catch (Exception e2) {
        }
        try {
            connection.close();
        } catch (Exception e2) {
        }
    }
}
Also used : MybatisSqlUtils(com.mendmix.mybatis.kit.MybatisSqlUtils) Arrays(java.util.Arrays) SqlCommandType(org.apache.ibatis.mapping.SqlCommandType) Connection(java.sql.Connection) MybatisConfigs(com.mendmix.mybatis.MybatisConfigs) LoggerFactory(org.slf4j.LoggerFactory) CacheExpires(com.mendmix.cache.CacheExpires) MapperMetadata(com.mendmix.mybatis.metadata.MapperMetadata) StringUtils(org.apache.commons.lang3.StringUtils) CrudMethods(com.mendmix.mybatis.crud.CrudMethods) ResultSet(java.sql.ResultSet) Map(java.util.Map) ParameterMapping(org.apache.ibatis.mapping.ParameterMapping) Cache(com.mendmix.mybatis.plugin.cache.annotation.Cache) MybatisRuntimeContext(com.mendmix.mybatis.MybatisRuntimeContext) Method(java.lang.reflect.Method) DigestUtils(com.mendmix.common.util.DigestUtils) AuthUser(com.mendmix.common.model.AuthUser) InstanceFactory(com.mendmix.spring.InstanceFactory) Collection(java.util.Collection) Set(java.util.Set) ColumnMetadata(com.mendmix.mybatis.metadata.ColumnMetadata) PreparedStatement(java.sql.PreparedStatement) MapperMethod(com.mendmix.mybatis.metadata.MapperMetadata.MapperMethod) Collectors(java.util.stream.Collectors) StandardThreadFactory(com.mendmix.common.async.StandardThreadExecutor.StandardThreadFactory) MybatisMapperParser(com.mendmix.mybatis.parser.MybatisMapperParser) Executors(java.util.concurrent.Executors) Serializable(java.io.Serializable) BaseEntity(com.mendmix.mybatis.core.BaseEntity) List(java.util.List) MybatisHanlerInitException(com.mendmix.mybatis.exception.MybatisHanlerInitException) Annotation(java.lang.annotation.Annotation) GlobalConstants(com.mendmix.common.GlobalConstants) JsonUtils(com.mendmix.common.util.JsonUtils) ReflectUtils(com.mendmix.common.util.ReflectUtils) InvocationVals(com.mendmix.mybatis.plugin.InvocationVals) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) SqlMetadata(com.mendmix.mybatis.metadata.SqlMetadata) InterceptorHandler(com.mendmix.mybatis.core.InterceptorHandler) BoundSql(org.apache.ibatis.mapping.BoundSql) Table(javax.persistence.Table) CacheKeyUtils(com.mendmix.mybatis.kit.CacheKeyUtils) DataSource(javax.sql.DataSource) CacheUtils(com.mendmix.cache.CacheUtils) FieldUtils(org.apache.commons.lang3.reflect.FieldUtils) ExecutorService(java.util.concurrent.ExecutorService) Id(javax.persistence.Id) Param(org.apache.ibatis.annotations.Param) CurrentRuntimeContext(com.mendmix.common.CurrentRuntimeContext) Logger(org.slf4j.Logger) CacheIgnore(com.mendmix.mybatis.plugin.cache.annotation.CacheIgnore) Field(java.lang.reflect.Field) JeesuiteMybatisInterceptor(com.mendmix.mybatis.plugin.JeesuiteMybatisInterceptor) MappedStatement(org.apache.ibatis.mapping.MappedStatement) SqlRewriteHandler(com.mendmix.mybatis.plugin.rewrite.SqlRewriteHandler) Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) ArrayList(java.util.ArrayList) PreparedStatement(java.sql.PreparedStatement) MybatisHanlerInitException(com.mendmix.mybatis.exception.MybatisHanlerInitException)

Example 2 with SqlMetadata

use of com.mendmix.mybatis.metadata.SqlMetadata in project jeesuite-libs by vakinge.

the class CacheHandler method onFinished.

@SuppressWarnings("rawtypes")
@Override
public void onFinished(InvocationVals invocationVal, Object result) {
    try {
        if (BLOCK_ON_CONCURRENT_LOCK_RETURN.equals(result))
            return;
        MappedStatement mt = invocationVal.getMappedStatement();
        QueryCacheMethodMetadata metadata = null;
        if (mt.getSqlCommandType().equals(SqlCommandType.SELECT)) {
            if (result == null)
                return;
            if ((metadata = invocationVal.getQueryMethodMetadata()) == null)
                return;
            final String cacheKey = invocationVal.getCacheKey();
            if (result instanceof List) {
                List list = (List) result;
                if (list.isEmpty()) {
                    if (nullValueCache) {
                        CacheUtils.set(cacheKey, NULL_PLACEHOLDER, IN_1MINS);
                    }
                    return;
                }
                result = metadata.collectionResult ? result : list.get(0);
            }
            // 
            if (!metadata.isSecondQueryById()) {
                CacheUtils.set(cacheKey, result, metadata.getExpire());
                if (logger.isDebugEnabled())
                    logger.debug(">>auto_cache_process addCache -> mapperId:{},cacheKey:{}", mt.getId(), cacheKey);
                if (metadata.isPk) {
                    // 唯一索引(业务上)
                    cacheUniqueSelectRef(invocationVal, result, mt, cacheKey);
                } else if (metadata.groupRalated) {
                    // 结果为集合的情况,增加key到cacheGroup
                    CacheUtils.addListItems(metadata.cacheGroupKey, cacheKey);
                }
            } else {
                // 之前没有按主键的缓存,增加按主键缓存
                String idCacheKey = genarateQueryCacheKey(invocationVal, getQueryByPkMethodCache(mt.getId()).keyPattern, result);
                if (idCacheKey != null && cacheKey != null) {
                    if (!CacheUtils.exists(idCacheKey)) {
                        // 缓存idkey->实体
                        CacheUtils.set(idCacheKey, result, metadata.getExpire());
                    }
                    // 缓存fieldkey->idkey
                    cacheFieldRefKey(cacheKey, idCacheKey, metadata.getExpire());
                    if (logger.isDebugEnabled())
                        logger.debug(">>auto_cache_process addCache -> mapperId:{},idCacheKey:{},cacheKey:{}", mt.getId(), idCacheKey, cacheKey);
                }
            }
        } else {
            String mapperClassName = invocationVal.getMapperNameSpace();
            if (!cacheEnableMappers.contains(mapperClassName) && !customUpdateCacheMapppings.containsKey(mt.getId()))
                return;
            // 返回0,未更新成功
            if (result != null && ((int) result) == 0)
                return;
            // 更新方法移除缓存,避免事务回滚导致缓存不一致,所以更新方法直接移除缓存
            if (mt.getSqlCommandType().equals(SqlCommandType.INSERT)) {
            // TODO 写入缓存 ,考虑回滚
            } else {
                if (updatePkCacheMethods.containsKey(mt.getId())) {
                    UpdateByPkCacheMethodMetadata updateMethodCache = updatePkCacheMethods.get(mt.getId());
                    String idCacheKey = genarateQueryCacheKey(invocationVal, updateMethodCache.keyPattern, invocationVal.getParameter());
                    CacheUtils.remove(idCacheKey);
                } else {
                    // 针对按条件更新或者删除的方法,按查询条件查询相关内容,然后清理对应主键缓存内容
                    MapperMetadata mapperMeta = MybatisMapperParser.getMapperMetadata(mapperClassName);
                    final Object parameter = invocationVal.getArgs()[1];
                    BoundSql boundSql = mt.getBoundSql(parameter);
                    String orignSql = boundSql.getSql();
                    ColumnMetadata idColumn = mapperMeta.getEntityMetadata().getIdColumn();
                    SqlMetadata sqlMetadata = MybatisSqlUtils.rewriteAsSelectPkField(orignSql, idColumn.getColumn());
                    // 
                    String tenantId = CurrentRuntimeContext.getTenantId();
                    cleanCacheExecutor.execute(new Runnable() {

                        @Override
                        public void run() {
                            if (tenantId != null) {
                                CurrentRuntimeContext.setTenantId(tenantId);
                            }
                            removeCacheByDyncQuery(mapperMeta, boundSql, sqlMetadata);
                        }
                    });
                }
            }
            // 删除同一cachegroup关联缓存
            removeCacheByGroup(mt.getId(), mapperClassName);
            // 删除自定义关联缓存
            if (customUpdateCacheMapppings.containsKey(mt.getId())) {
                removeCustomRelateCache(mt.getId());
            }
        }
    } finally {
        // 清除并发控制锁
        if (invocationVal.getConcurrentLockKey() != null) {
            CacheUtils.remove(invocationVal.getConcurrentLockKey());
        }
    }
}
Also used : ColumnMetadata(com.mendmix.mybatis.metadata.ColumnMetadata) BoundSql(org.apache.ibatis.mapping.BoundSql) List(java.util.List) ArrayList(java.util.ArrayList) SqlMetadata(com.mendmix.mybatis.metadata.SqlMetadata) MappedStatement(org.apache.ibatis.mapping.MappedStatement) MapperMetadata(com.mendmix.mybatis.metadata.MapperMetadata)

Example 3 with SqlMetadata

use of com.mendmix.mybatis.metadata.SqlMetadata in project jeesuite-libs by vakinge.

the class MybatisSqlUtils method rewriteAsSelectPkField.

public static SqlMetadata rewriteAsSelectPkField(String sql, String idColumnName) {
    try {
        Statement statement = CCJSqlParserUtil.parse(sql);
        Table table = null;
        Expression where = null;
        int startIndex = 0;
        int endIndex = 0;
        if (statement instanceof Update) {
            Update update = (Update) statement;
            table = update.getTable();
            where = update.getWhere();
            startIndex = StringUtils.countMatches(update.getExpressions().toString(), SQL_PARAMETER_PLACEHOLDER);
            endIndex = startIndex;
        } else if (statement instanceof Delete) {
            Delete delete = (Delete) statement;
            table = delete.getTable();
            where = delete.getWhere();
        } else {
            return null;
        }
        PlainSelect selectBody = new PlainSelect();
        selectBody.setFromItem(table);
        SelectExpressionItem selectItem = new SelectExpressionItem(new Column(idColumnName));
        selectBody.setSelectItems(Arrays.asList(selectItem));
        selectBody.setWhere(where);
        Select select = new Select();
        select.setSelectBody(selectBody);
        String rewriteSql = selectBody.toString();
        while (rewriteSql.contains(SQL_PARAMETER_PLACEHOLDER)) {
            rewriteSql = StringUtils.replaceOnce(rewriteSql, SQL_PARAMETER_PLACEHOLDER, "{x}");
            endIndex++;
        }
        // 
        rewriteSql = StringUtils.replace(rewriteSql, "{x}", SQL_PARAMETER_PLACEHOLDER);
        return new SqlMetadata(rewriteSql, table.getName(), startIndex, endIndex - 1);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
Also used : Delete(net.sf.jsqlparser.statement.delete.Delete) Table(net.sf.jsqlparser.schema.Table) Statement(net.sf.jsqlparser.statement.Statement) SelectExpressionItem(net.sf.jsqlparser.statement.select.SelectExpressionItem) PlainSelect(net.sf.jsqlparser.statement.select.PlainSelect) SqlMetadata(com.mendmix.mybatis.metadata.SqlMetadata) Update(net.sf.jsqlparser.statement.update.Update) SQLException(java.sql.SQLException) Expression(net.sf.jsqlparser.expression.Expression) Column(net.sf.jsqlparser.schema.Column) PlainSelect(net.sf.jsqlparser.statement.select.PlainSelect) Select(net.sf.jsqlparser.statement.select.Select)

Aggregations

SqlMetadata (com.mendmix.mybatis.metadata.SqlMetadata)3 ColumnMetadata (com.mendmix.mybatis.metadata.ColumnMetadata)2 MapperMetadata (com.mendmix.mybatis.metadata.MapperMetadata)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 BoundSql (org.apache.ibatis.mapping.BoundSql)2 MappedStatement (org.apache.ibatis.mapping.MappedStatement)2 CacheExpires (com.mendmix.cache.CacheExpires)1 CacheUtils (com.mendmix.cache.CacheUtils)1 CurrentRuntimeContext (com.mendmix.common.CurrentRuntimeContext)1 GlobalConstants (com.mendmix.common.GlobalConstants)1 StandardThreadFactory (com.mendmix.common.async.StandardThreadExecutor.StandardThreadFactory)1 AuthUser (com.mendmix.common.model.AuthUser)1 DigestUtils (com.mendmix.common.util.DigestUtils)1 JsonUtils (com.mendmix.common.util.JsonUtils)1 ReflectUtils (com.mendmix.common.util.ReflectUtils)1 MybatisConfigs (com.mendmix.mybatis.MybatisConfigs)1 MybatisRuntimeContext (com.mendmix.mybatis.MybatisRuntimeContext)1 BaseEntity (com.mendmix.mybatis.core.BaseEntity)1 InterceptorHandler (com.mendmix.mybatis.core.InterceptorHandler)1