Skip to content

Commit

Permalink
refactor(data/mybatis-plus): 移动枚举接口到 core 模块,和 MP IEnum 枚举接口解耦
Browse files Browse the repository at this point in the history
  • Loading branch information
Charles7c committed Jul 30, 2024
1 parent 8bacd87 commit b27fbd4
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
* limitations under the License.
*/

package top.continew.starter.data.mybatis.plus.base;

import com.baomidou.mybatisplus.annotation.IEnum;
package top.continew.starter.core.enums;

import java.io.Serializable;

Expand All @@ -27,7 +25,14 @@
* @author Charles7c
* @since 1.0.0
*/
public interface IBaseEnum<T extends Serializable> extends IEnum<T> {
public interface BaseEnum<T extends Serializable> {

/**
* 枚举值
*
* @return 枚举值
*/
T getValue();

/**
* 枚举描述
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package top.continew.starter.data.mybatis.plus.autoconfigure;

import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
Expand All @@ -40,6 +41,7 @@
import top.continew.starter.data.mybatis.plus.autoconfigure.idgenerator.MyBatisPlusIdGeneratorConfiguration;
import top.continew.starter.data.mybatis.plus.datapermission.DataPermissionFilter;
import top.continew.starter.data.mybatis.plus.datapermission.DataPermissionHandlerImpl;
import top.continew.starter.data.mybatis.plus.handler.MybatisBaseEnumTypeHandler;

/**
* MyBatis Plus 自动配置
Expand All @@ -57,6 +59,16 @@ public class MybatisPlusAutoConfiguration {

private static final Logger log = LoggerFactory.getLogger(MybatisPlusAutoConfiguration.class);

/**
* MyBatis Plus 配置
*
* @since 2.4.0
*/
@Bean
public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() {
return properties -> properties.getConfiguration().setDefaultEnumTypeHandler(MybatisBaseEnumTypeHandler.class);
}

/**
* MyBatis Plus 插件配置
*/
Expand All @@ -65,11 +77,9 @@ public class MybatisPlusAutoConfiguration {
public MybatisPlusInterceptor mybatisPlusInterceptor(MyBatisPlusExtensionProperties properties) {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 数据权限插件
MyBatisPlusExtensionProperties.DataPermissionProperties dataPermissionProperties = properties
.getDataPermission();
MyBatisPlusExtensionProperties.DataPermissionProperties dataPermissionProperties = properties.getDataPermission();
if (null != dataPermissionProperties && dataPermissionProperties.isEnabled()) {
interceptor.addInnerInterceptor(new DataPermissionInterceptor(SpringUtil
.getBean(DataPermissionHandler.class)));
interceptor.addInnerInterceptor(new DataPermissionInterceptor(SpringUtil.getBean(DataPermissionHandler.class)));
}
// 分页插件
MyBatisPlusExtensionProperties.PaginationProperties paginationProperties = properties.getPagination();
Expand All @@ -89,8 +99,7 @@ public MybatisPlusInterceptor mybatisPlusInterceptor(MyBatisPlusExtensionPropert
@Configuration
@Import({MyBatisPlusIdGeneratorConfiguration.Default.class, MyBatisPlusIdGeneratorConfiguration.CosId.class,
MyBatisPlusIdGeneratorConfiguration.Custom.class})
protected static class MyBatisPlusIdGeneratorAutoConfiguration {
}
protected static class MyBatisPlusIdGeneratorAutoConfiguration {}

/**
* 数据权限处理器
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.continew.starter.data.mybatis.plus.handler;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaClass;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.invoker.Invoker;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import top.continew.starter.core.enums.BaseEnum;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
* 自定义枚举属性转换器
*
* @author hubin
* @author Charles7c
* @since 2.4.0
*/
public class MybatisBaseEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {

private static final Map<String, String> TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap<>();
private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();
private final Class<E> enumClassType;
private final Class<?> propertyType;
private final Invoker getInvoker;

public MybatisBaseEnumTypeHandler(Class<E> enumClassType) {
if (enumClassType == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.enumClassType = enumClassType;
MetaClass metaClass = MetaClass.forClass(enumClassType, REFLECTOR_FACTORY);
String name = "value";
if (!BaseEnum.class.isAssignableFrom(enumClassType) && !IEnum.class.isAssignableFrom(enumClassType)) {
name = findEnumValueFieldName(this.enumClassType).orElseThrow(() -> new IllegalArgumentException(String
.format("Could not find @EnumValue in Class: %s.", this.enumClassType.getName())));
}
this.propertyType = ReflectionKit.resolvePrimitiveIfNecessary(metaClass.getGetterType(name));
this.getInvoker = metaClass.getGetInvoker(name);
}

/**
* 查找标记标记EnumValue字段
*
* @param clazz class
* @return EnumValue字段
*/
public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
if (clazz != null && clazz.isEnum()) {
String className = clazz.getName();
return Optional.ofNullable(CollectionUtils.computeIfAbsent(TABLE_METHOD_OF_ENUM_TYPES, className, key -> {
Optional<Field> fieldOptional = findEnumValueAnnotationField(clazz);
return fieldOptional.map(Field::getName).orElse(null);
}));
}
return Optional.empty();
}

private static Optional<Field> findEnumValueAnnotationField(Class<?> clazz) {
return Arrays.stream(clazz.getDeclaredFields())
.filter(field -> field.isAnnotationPresent(EnumValue.class))
.findFirst();
}

/**
* 判断是否为MP枚举处理
*
* @param clazz class
* @return 是否为MP枚举处理
*/
public static boolean isMpEnums(Class<?> clazz) {
return clazz != null && clazz.isEnum() && (BaseEnum.class.isAssignableFrom(clazz) || IEnum.class
.isAssignableFrom(clazz) || findEnumValueFieldName(clazz).isPresent());
}

@SuppressWarnings("Duplicates")
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setObject(i, this.getValue(parameter));
} else {
// see r3589
ps.setObject(i, this.getValue(parameter), jdbcType.TYPE_CODE);
}
}

@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
Object value = rs.getObject(columnName, this.propertyType);
if (null == value || rs.wasNull()) {
return null;
}
return this.valueOf(value);
}

@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Object value = rs.getObject(columnIndex, this.propertyType);
if (null == value || rs.wasNull()) {
return null;
}
return this.valueOf(value);
}

@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Object value = cs.getObject(columnIndex, this.propertyType);
if (null == value || cs.wasNull()) {
return null;
}
return this.valueOf(value);
}

private E valueOf(Object value) {
E[] es = this.enumClassType.getEnumConstants();
return Arrays.stream(es).filter(e -> equalsValue(value, getValue(e))).findAny().orElse(null);
}

/**
* 值比较
*
* @param sourceValue 数据库字段值
* @param targetValue 当前枚举属性值
* @return 是否匹配
*/
private boolean equalsValue(Object sourceValue, Object targetValue) {
String sValue = StringUtils.toStringTrim(sourceValue);
String tValue = StringUtils.toStringTrim(targetValue);
if (sourceValue instanceof Number && targetValue instanceof Number && new BigDecimal(sValue)
.compareTo(new BigDecimal(tValue)) == 0) {
return true;
}
return Objects.equals(sValue, tValue);
}

private Object getValue(Object object) {
try {
return this.getInvoker.invoke(object, new Object[0]);
} catch (ReflectiveOperationException e) {
throw ExceptionUtils.mpe(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.data.mybatis.plus.base.IBaseEnum;
import top.continew.starter.core.enums.BaseEnum;

/**
* Easy Excel 枚举接口转换器
*
* @see IBaseEnum
* @see BaseEnum
* @author Charles7c
* @since 1.2.0
*/
public class ExcelBaseEnumConverter implements Converter<IBaseEnum<Integer>> {
public class ExcelBaseEnumConverter implements Converter<BaseEnum<Integer>> {

@Override
public Class<IBaseEnum> supportJavaTypeKey() {
return IBaseEnum.class;
public Class<BaseEnum> supportJavaTypeKey() {
return BaseEnum.class;
}

@Override
Expand All @@ -50,17 +50,17 @@ public CellDataTypeEnum supportExcelTypeKey() {
* 转换为 Java 数据(读取 Excel)
*/
@Override
public IBaseEnum convertToJavaData(ReadCellData<?> cellData,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return this.getEnum(IBaseEnum.class, Convert.toStr(cellData.getData()));
public BaseEnum convertToJavaData(ReadCellData<?> cellData,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return this.getEnum(BaseEnum.class, Convert.toStr(cellData.getData()));
}

/**
* 转换为 Excel 数据(写入 Excel)
*/
@Override
public WriteCellData<String> convertToExcelData(IBaseEnum<Integer> value,
public WriteCellData<String> convertToExcelData(BaseEnum<Integer> value,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (null == value) {
Expand All @@ -76,11 +76,11 @@ public WriteCellData<String> convertToExcelData(IBaseEnum<Integer> value,
* @param description 描述
* @return 对应枚举 ,获取不到时为 {@code null}
*/
private IBaseEnum<Integer> getEnum(Class<?> enumType, String description) {
private BaseEnum<Integer> getEnum(Class<?> enumType, String description) {
Object[] enumConstants = enumType.getEnumConstants();
for (Object enumConstant : enumConstants) {
if (ClassUtil.isAssignable(IBaseEnum.class, enumType)) {
IBaseEnum<Integer> baseEnum = (IBaseEnum<Integer>)enumConstant;
if (ClassUtil.isAssignable(BaseEnum.class, enumType)) {
BaseEnum<Integer> baseEnum = (BaseEnum<Integer>)enumConstant;
if (baseEnum.getDescription().equals(description)) {
return baseEnum;
}
Expand Down

0 comments on commit b27fbd4

Please sign in to comment.