All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.zodiac.mybatisplus.interceptor.AbstractOptimisticLockerInterceptor Maven / Gradle / Ivy
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;
}
}