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

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

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

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.zodiac.sdk.toolkit.constants.StringPool;
import org.zodiac.sdk.toolkit.util.SystemClock;

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;

/**
 * 提供以下 {@link OptimisticLockerInnerInterceptor} 不具备的功能。
 * 
*
    *
  • 当乐观锁字段值为 null 时使用默认值。
  • *
  • 刷新实体对象的乐观锁字段值。
  • *
  • 支持 {@link java.sql.Date}、{@link java.sql.Time}、{@link LocalDate}、{@link LocalTime}作为乐观做字段的类型。
  • *
*
* */ public abstract class AbstractOptimisticLockerInterceptor implements InnerInterceptor { private static final String PARAM_UPDATE_METHOD_NAME = "update"; private static final Boolean USE_VERSION_DEFAULT_IF_NULL = Boolean.FALSE; private static final Boolean REFRESH_VERSION_FIELD_VALUE = Boolean.TRUE; /** * 乐观锁字段值为null时是否使用默认值。 */ private final AtomicReference useVersionDefaultIfNullRef = new AtomicReference<>(); /** * 乐观锁字段值为null时是否使用默认值。 */ private final AtomicReference refreshVersionFieldValueRef = new AtomicReference<>(); public AbstractOptimisticLockerInterceptor() { } public AbstractOptimisticLockerInterceptor(boolean useVersionDefaultIfNull) { setUseVersionDefaultIfNull(useVersionDefaultIfNull); } public AbstractOptimisticLockerInterceptor(boolean useVersionDefaultIfNull, boolean refreshVersionFieldValue) { setUseVersionDefaultIfNull(useVersionDefaultIfNull); setRefetchVersionFieldValueRef(refreshVersionFieldValue); } @Override public void beforeUpdate(Executor executor, MappedStatement mappedStatement, Object parameter) throws SQLException { if (SqlCommandType.UPDATE != mappedStatement.getSqlCommandType()) { return; } if (parameter instanceof Map) { Map map = (Map) parameter; doOptimisticLocker(executor, mappedStatement, parameter, map, mappedStatement.getId()); } } public AbstractOptimisticLockerInterceptor setUseVersionDefaultIfNull(boolean useVersionDefaultIfNull) { this.useVersionDefaultIfNullRef.compareAndSet(null, Boolean.valueOf(useVersionDefaultIfNull)); return this; } public AbstractOptimisticLockerInterceptor setRefetchVersionFieldValueRef(boolean refreshVersionFieldValue) { this.refreshVersionFieldValueRef.compareAndSet(null, Boolean.valueOf(refreshVersionFieldValue)); return this; } protected boolean isUseVersionDefaultIfNull() { return Optional.ofNullable(useVersionDefaultIfNullRef.get()).orElse(USE_VERSION_DEFAULT_IF_NULL).booleanValue(); } protected boolean isRefetchVersionFieldValue() { return Optional.ofNullable(refreshVersionFieldValueRef.get()).orElse(REFRESH_VERSION_FIELD_VALUE).booleanValue(); } protected void doOptimisticLocker(Executor executor, MappedStatement mappedStatement, Object parameter, Map map, String msId) { /*updateById(et), update(et, wrapper);*/ Object et = map.getOrDefault(Constants.ENTITY, null); if (et != null) { /*entity*/ String methodName = msId.substring(msId.lastIndexOf(StringPool.DOT) + 1); TableInfo tableInfo = TableInfoHelper.getTableInfo(et.getClass()); if (tableInfo == null || !tableInfo.isWithVersion()) { return; } try { TableFieldInfo fieldInfo = tableInfo.getVersionFieldInfo(); Field versionField = fieldInfo.getField(); /*旧的 version 值*/ Object originalVersionVal = getVersionFieldValue(executor, et, versionField); if (originalVersionVal == null) { /*乐观锁字段为null。父类实现为直接返回,这里尝试获取*/ if (isUseVersionDefaultIfNull()) { originalVersionVal = getVersionDefaultIfNull(versionField.getDeclaringClass()); } if (originalVersionVal == null) { return; } } String versionColumn = fieldInfo.getColumn(); /*新的 version 值*/ Object updatedVersionVal = this.getUpdatedVersionVal(fieldInfo.getPropertyType(), originalVersionVal); if (PARAM_UPDATE_METHOD_NAME.equals(methodName)) { AbstractWrapper aw = (AbstractWrapper) map.getOrDefault(Constants.WRAPPER, null); if (aw == null) { UpdateWrapper uw = new UpdateWrapper<>(); uw.eq(versionColumn, originalVersionVal); map.put(Constants.WRAPPER, uw); } else { aw.apply(versionColumn + " = {0}", originalVersionVal); } } else { map.put(Constants.MP_OPTLOCK_VERSION_ORIGINAL, originalVersionVal); } versionField.set(et, updatedVersionVal); } catch (IllegalAccessException e) { throw ExceptionUtils.mpe(e); } } } /** * 取得实体对象乐观锁字段的值。 * * @param executor 执行器 * @param entity 实体对象 * @param versionField 乐观锁字段 * @return 乐观锁字段的值 * @throws IllegalAccessException 属性访问异常 * @throws IllegalArgumentException 参数错误异常 */ protected Object getVersionFieldValue(Executor executor, Object entity, Field versionField) throws IllegalArgumentException, IllegalAccessException { if (null == entity || null == versionField) { return null; } if (isRefetchVersionFieldValue()) { /*需要刷新乐观锁字段的值*/ versionField = getRefreshedVersionVal(executor, entity, versionField); } return versionField.get(entity); } /** * 当取得乐观锁字段的初始化值为null时的默认值。 * * @param clazz 乐观锁字段类型 * @return 默认值 */ protected Object getVersionDefaultIfNull(Class clazz) { if (long.class.equals(clazz) || Long.class.equals(clazz)) { return Long.valueOf(0L); } else if (int.class.equals(clazz) || Integer.class.equals(clazz)) { return Integer.valueOf(0); } else if (Date.class.equals(clazz)) { return new Date(); } else if (java.sql.Time.class.equals(clazz)) { return new java.sql.Time(SystemClock.nowTimeMillis()); } else if (java.sql.Date.class.equals(clazz)) { return new java.sql.Date(SystemClock.nowTimeMillis()); } else if (Timestamp.class.equals(clazz)) { return new Timestamp(SystemClock.nowTimeMillis()); } else if (LocalDate.class.equals(clazz)) { return LocalDate.now(); } else if (LocalTime.class.equals(clazz)) { return LocalTime.now(); } else if (LocalDateTime.class.equals(clazz)) { return LocalDateTime.now(); } return null; } protected Object getUpdatedVersionVal(Class clazz, Object originalVersionVal) { if (long.class.equals(clazz) || Long.class.equals(clazz)) { return ((long) originalVersionVal) + 1; } else if (int.class.equals(clazz) || Integer.class.equals(clazz)) { return ((int) originalVersionVal) + 1; } else if (Date.class.equals(clazz)) { return new Date(); } else if (java.sql.Time.class.equals(clazz)) { return new java.sql.Time(SystemClock.nowTimeMillis()); } else if (java.sql.Date.class.equals(clazz)) { return new java.sql.Date(SystemClock.nowTimeMillis()); } else if (Timestamp.class.equals(clazz)) { return new Timestamp(SystemClock.nowTimeMillis()); } else if (LocalDate.class.equals(clazz)) { return LocalDate.now(); } else if (LocalTime.class.equals(clazz)) { return LocalTime.now(); } else if (LocalDateTime.class.equals(clazz)) { return LocalDateTime.now(); } /*not supported type, return original val.*/ return originalVersionVal; } protected Field getRefreshedVersionVal(Executor executor, Object entity, Field versionField) { /*默认实现不做任何处理,留给之类实现。*/ return versionField; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy