All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.mybatisplus.interceptor.MyBatisPreparedBeanMapperInterceptor Maven / Gradle / Ivy

There is a newer version: 1.6.8
Show newest version
package org.zodiac.mybatisplus.interceptor;

import java.util.Iterator;
import java.util.Objects;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.zodiac.commons.logging.SmartSlf4jLogger;
import org.zodiac.commons.logging.SmartSlf4jLoggerFactory;
import org.zodiac.commons.remote.bridge.RpcContextHolderBridges;
import org.zodiac.commons.remote.bridge.RpcContextIamSecurityBridges;
import org.zodiac.commons.support.PageHolder;
import org.zodiac.commons.util.BeanUtil;
import org.zodiac.commons.util.IdGenerator;
import org.zodiac.mybatis.constants.MyBatisConstants;
import org.zodiac.mybatisplus.base.BaseEntity;
import org.zodiac.mybatisplus.base.BaseEntityInternalUtil;
import org.zodiac.sdk.toolkit.util.lang.NumUtil;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

/**
 * General {@link BaseEntity} property functions handle interceptors in a unified
 * way, for example, generating IDs for insertion methods (supports local or
 * remote generators)
*
* * In mybatis, there are four types that can be intercepted (in the order of * interception type):
*
* Executor:Method of intercepting actuator
* ParameterHandler:Processing of interception parameters
* ResultHandler:Processing of interception result set
* StatementHandler:Processing of intercepting SQL syntax construction
* * @see https://www.jianshu.com/p/0a72bb1f6a21 * @see https://cloud.tencent.com/developer/article/1170370 */ @Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }), @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) }) public class MyBatisPreparedBeanMapperInterceptor implements Interceptor { protected final SmartSlf4jLogger log = SmartSlf4jLoggerFactory.getLogger(getClass()); private IdGenerator idGenerator; public MyBatisPreparedBeanMapperInterceptor(IdGenerator idGenerator) { this.idGenerator = idGenerator; } @Override public Object plugin(Object target) { if (target instanceof Executor) { return Plugin.wrap(target, this); } else { return target; } } @Override public void setProperties(Properties properties) { } @Override public Object intercept(Invocation invoc) throws Throwable { if (Objects.isNull(invoc.getArgs())) { return invoc.proceed(); } MappedStatement statement = (MappedStatement) invoc.getArgs()[0]; SqlCommandType command = statement.getSqlCommandType(); /*Prepared properties.*/ preProcess(invoc, command); /*Invoke mapper process*/ final Object result = invoc.proceed(); /*Post properties.*/ return postProcess(invoc, command, result); } /** * Pre query properties set. (if necessary). * * @param invoc Invocation */ protected void preQuery(Invocation invoc) { /* * Note: In order to be compatible with the distributed microservice * architecture, it is not the best solution to convert the bean time * returned by Dao layer here. Because Dao layer may not be able to * obtain the I18N language of the current user, it is finally decided * to migrate to the web layer. */ if (Objects.isNull(PageHelper.getLocalPage())) { /*Not paging*/ /*Obtain page from rpc context.*/ PageHolder.Page page = PageHolder.InternalUtil.current(false); if (Objects.nonNull(page)) { log.debug("Begin current paging of: {}", page); PageHelper.startPage(page.getPageNum(), page.getPageSize(), page.isCount()); } } } /** * Pre updation properties set.(if necessary). * * @param invoc invocation */ protected void preUpdate(Invocation invoc) { for (int i = 1; i < invoc.getArgs().length; i++) { Object arg = invoc.getArgs()[i]; if (BaseEntity.class.isAssignableFrom(arg.getClass())) { BaseEntity bean = (BaseEntity) arg; if (isUpdateSettable(bean)) { bean.preUpdate(); bean.setUpdateUser(getCurrentPrincipalId()); } break; } } } /** * Pre insertion properties set.(if necessary). * * @param invoc Invocation */ @SuppressWarnings("rawtypes") protected void preInsert(Invocation invoc) { /*Sets insert properties*/ for (int i = 1; i < invoc.getArgs().length; i++) { Object arg = invoc.getArgs()[i]; if (BaseEntity.class.isAssignableFrom(arg.getClass())) { doPreInsert(invoc, (BaseEntity) arg); } else if (Iterable.class.isAssignableFrom(arg.getClass())) {/*e.g: UserDao#insertBatch(List)*/ Iterator it = ((Iterable) arg).iterator(); while (it.hasNext()) { Object value = it.next(); if (BaseEntity.class.isAssignableFrom(value.getClass())) { doPreInsert(invoc, (BaseEntity) arg); } } } } } protected void doPreInsert(Invocation invoc, BaseEntity bean) { /*Assign sets primary key ID.*/ if (!Objects.isNull(bean) && Objects.isNull(bean.getId())) { bean.setId(idGenerator.nextId(bean)); log.debug("Dynamic assigned primary key ID for: {}, method: {}", bean.getId(), invoc.getMethod()); } if (isInsertSettable(bean)) { bean.preInsert(); Long currentPrincipalId = getCurrentPrincipalId(); bean.setCreateUser(Objects.isNull(currentPrincipalId) ? MyBatisConstants.UNKNOWN_USER_ID : currentPrincipalId); bean.setUpdateUser(bean.getCreateUser()); } } /** * Post query properties set. (if necessary) * * @param invoc Invocation * @param result pre-processed result * @return processed result */ protected Object postQuery(Invocation invoc, Object result) { if (Objects.isNull(result)) { return null; } /*Update executed paging info to rpc server context.*/ if (result instanceof Page) { com.github.pagehelper.Page helperPage = (com.github.pagehelper.Page) result; PageHolder.Page currentPage = PageHolder.InternalUtil.current(false); if (Objects.nonNull(currentPage)) { BeanUtil.copyProperties(helperPage, currentPage); /* Rebind executed page information to rpc server context. Ensure that the information that has been paged can be obtained on the consumer service side. */ PageHolder.InternalUtil.bind(true, currentPage); /*Update current executed paging info.*/ PageHolder.InternalUtil.update(); log.debug("End current paging of: {}", currentPage); } } return result; } /** * Post updation properties set.(if necessary) * * @param invoc Invocation * @param result pre-processed result * @return processed result */ protected Object postUpdate(Invocation invoc, Object result) { return result; } /** * Post insertion properties set.(if necessary) * * @param invoc Invocation * @param result pre-processed result * @return processed result */ protected Object postInsert(Invocation invoc, Object result) { if (Objects.isNull(result)) { return null; } /*Sets the primary key value generated by inserted SQL to return to the caller.*/ for (int i = 1; i < invoc.getArgs().length; i++) { Object arg = invoc.getArgs()[i]; if (BaseEntity.class.isAssignableFrom(arg.getClass())) { BaseEntity bean = (BaseEntity) arg; if (RpcContextHolderBridges.hasRpcContextHolderClass()) { /*Distributed(cluster)?*/ RpcContextHolderBridges.invokeSet(true, BaseEntityInternalUtil.CURRENT_BEANID_KEY, bean.getId()); } } } return result; } /** * Check whether parameter properties need to be set when insertion. * * @param bean BaseEntity * @return inserting fields is settable */ protected boolean isInsertSettable(BaseEntity bean) { return Objects.isNull(bean.getCreateTime()) || Objects.isNull(bean.getCreateUser()); } /** * Check whether parameter properties need to be set when updating. * * @param bean BaseEntity * @return updating fields is settable */ protected boolean isUpdateSettable(BaseEntity bean) { return Objects.isNull(bean.getUpdateTime()) || Objects.isNull(bean.getUpdateUser()); } /** * Gets current login principalId. * * @return principal ID */ protected Long getCurrentPrincipalId() { if (RpcContextIamSecurityBridges.hasRpcContextIamSecurityUtilsClass()) { try { /*TODO remove parse, direct use string principalId.*/ return NumUtil.toLongObjectOrNull(RpcContextIamSecurityBridges.currentIamPrincipalId()); } catch (Exception e) { log.warn("Cannot get currentIamPrincipalId. - {}", e.getMessage()); } } else { log.warn("Saving unable to set currentIamPrincipalId! Please check if 'xcloud-iam-common' dependency exists!"); } return MyBatisConstants.UNKNOWN_USER_ID; } private void preProcess(Invocation invoc, SqlCommandType command) { switch (command) { case SELECT: preQuery(invoc); break; case UPDATE: preUpdate(invoc); break; case INSERT: preInsert(invoc); break; default: } } private Object postProcess(Invocation invoc, SqlCommandType command, Object result) { switch (command) { case SELECT: return postQuery(invoc, result); case UPDATE: return postUpdate(invoc, result); case INSERT: return postInsert(invoc, result); default: return result; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy