mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-07 00:58:24 +08:00
feature: 为 entity 添加枚举属性的支持 close #I6W15K
This commit is contained in:
parent
254b58678c
commit
745c89683e
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <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 com.mybatisflex.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
public @interface EnumValue {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <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 com.mybatisflex.core.handler;
|
||||||
|
|
||||||
|
import com.mybatisflex.annotation.EnumValue;
|
||||||
|
import com.mybatisflex.core.util.ClassUtil;
|
||||||
|
import org.apache.ibatis.type.EnumTypeHandler;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
import org.apache.ibatis.type.TypeHandler;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.sql.CallableStatement;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CompositeEnumTypeHandler<E extends Enum<E>> implements TypeHandler<E> {
|
||||||
|
|
||||||
|
private final TypeHandler<E> delegate;
|
||||||
|
|
||||||
|
public CompositeEnumTypeHandler(Class<E> enumClass) {
|
||||||
|
List<Field> enumDbValueFields = ClassUtil.getAllFields(enumClass, f -> f.getAnnotation(EnumValue.class) != null);
|
||||||
|
if (enumDbValueFields.isEmpty()) {
|
||||||
|
delegate = new EnumTypeHandler<>(enumClass);
|
||||||
|
} else {
|
||||||
|
delegate = new FlexEnumTypeHandler<>(enumClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
|
||||||
|
delegate.setParameter(ps, i, parameter, jdbcType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E getResult(ResultSet rs, String columnName) throws SQLException {
|
||||||
|
return delegate.getResult(rs, columnName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E getResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||||
|
return delegate.getResult(rs, columnIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E getResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||||
|
return delegate.getResult(cs, columnIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <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 com.mybatisflex.core.handler;
|
||||||
|
|
||||||
|
import com.mybatisflex.annotation.EnumValue;
|
||||||
|
import com.mybatisflex.core.exception.FlexExceptions;
|
||||||
|
import com.mybatisflex.core.util.ClassUtil;
|
||||||
|
import com.mybatisflex.core.util.StringUtil;
|
||||||
|
import org.apache.ibatis.type.BaseTypeHandler;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.sql.CallableStatement;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FlexEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
|
||||||
|
|
||||||
|
private Class<?> enumPropertyType;
|
||||||
|
private E[] enums;
|
||||||
|
private Method getter;
|
||||||
|
|
||||||
|
public FlexEnumTypeHandler(Class<E> enumClass) {
|
||||||
|
|
||||||
|
List<Field> allFields = ClassUtil.getAllFields(enumClass, field -> field.getAnnotation(EnumValue.class) != null);
|
||||||
|
Field field = allFields.get(0);
|
||||||
|
|
||||||
|
List<Method> allMethods = ClassUtil.getAllMethods(enumClass, method -> {
|
||||||
|
String methodName = method.getName();
|
||||||
|
return methodName.equals("get" + StringUtil.firstCharToUpperCase(field.getName()));
|
||||||
|
});
|
||||||
|
|
||||||
|
enumPropertyType = field.getType();
|
||||||
|
enums = enumClass.getEnumConstants();
|
||||||
|
getter = allMethods.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
|
||||||
|
Object value = getValue(parameter);
|
||||||
|
if (jdbcType == null) {
|
||||||
|
ps.setObject(i, value);
|
||||||
|
} else {
|
||||||
|
ps.setObject(i, value, jdbcType.TYPE_CODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Object getValue(Object object) {
|
||||||
|
try {
|
||||||
|
return this.getter.invoke(object);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw FlexExceptions.wrap(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||||
|
Object value = rs.getObject(columnName, this.enumPropertyType);
|
||||||
|
if (null == value && rs.wasNull()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return convertToEnum(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||||
|
Object value = rs.getObject(columnIndex, this.enumPropertyType);
|
||||||
|
if (null == value && rs.wasNull()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return convertToEnum(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||||
|
Object value = cs.getObject(columnIndex, this.enumPropertyType);
|
||||||
|
if (null == value && cs.wasNull()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return convertToEnum(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private E convertToEnum(Object value) {
|
||||||
|
for (E e : enums) {
|
||||||
|
if (value.equals(getValue(e))) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.mybatisflex.core.table;
|
package com.mybatisflex.core.table;
|
||||||
|
|
||||||
|
import com.mybatisflex.core.handler.CompositeEnumTypeHandler;
|
||||||
import com.mybatisflex.core.mask.MaskTypeHandler;
|
import com.mybatisflex.core.mask.MaskTypeHandler;
|
||||||
import com.mybatisflex.core.util.StringUtil;
|
import com.mybatisflex.core.util.StringUtil;
|
||||||
import org.apache.ibatis.type.JdbcType;
|
import org.apache.ibatis.type.JdbcType;
|
||||||
@ -51,7 +52,6 @@ public class ColumnInfo {
|
|||||||
protected String maskType;
|
protected String maskType;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getColumn() {
|
public String getColumn() {
|
||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
@ -87,12 +87,16 @@ public class ColumnInfo {
|
|||||||
public TypeHandler buildTypeHandler() {
|
public TypeHandler buildTypeHandler() {
|
||||||
|
|
||||||
//优先使用自定义的 typeHandler
|
//优先使用自定义的 typeHandler
|
||||||
if (typeHandler != null){
|
if (typeHandler != null) {
|
||||||
return typeHandler;
|
return typeHandler;
|
||||||
}
|
}
|
||||||
|
//枚举
|
||||||
|
else if (propertyType.isEnum()) {
|
||||||
|
typeHandler = new CompositeEnumTypeHandler(propertyType);
|
||||||
|
}
|
||||||
//若用户未定义 typeHandler,而配置了数据脱敏,则使用脱敏的 handler 处理
|
//若用户未定义 typeHandler,而配置了数据脱敏,则使用脱敏的 handler 处理
|
||||||
else if (StringUtil.isNotBlank(maskType)){
|
else if (StringUtil.isNotBlank(maskType)) {
|
||||||
typeHandler = new MaskTypeHandler(maskType);
|
typeHandler = new MaskTypeHandler(maskType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeHandler;
|
return typeHandler;
|
||||||
|
|||||||
@ -173,6 +173,7 @@ public class TableInfoFactory {
|
|||||||
|
|
||||||
//未配置 typeHandler 的情况下,只支持基本数据类型,不支持比如 list set 或者自定义的类等
|
//未配置 typeHandler 的情况下,只支持基本数据类型,不支持比如 list set 或者自定义的类等
|
||||||
if ((column == null || column.typeHandler() == UnknownTypeHandler.class)
|
if ((column == null || column.typeHandler() == UnknownTypeHandler.class)
|
||||||
|
&& !field.getType().isEnum()
|
||||||
&& !defaultSupportColumnTypes.contains(field.getType())) {
|
&& !defaultSupportColumnTypes.contains(field.getType())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,22 +144,29 @@ public class ClassUtil {
|
|||||||
|
|
||||||
public static List<Field> getAllFields(Class<?> cl) {
|
public static List<Field> getAllFields(Class<?> cl) {
|
||||||
List<Field> fields = new ArrayList<>();
|
List<Field> fields = new ArrayList<>();
|
||||||
doGetFields(cl, fields);
|
doGetFields(cl, fields, null);
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Field> getAllFields(Class<?> cl, Predicate<Field> predicate) {
|
||||||
|
List<Field> fields = new ArrayList<>();
|
||||||
|
doGetFields(cl, fields, predicate);
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
private static void doGetFields(Class<?> cl, List<Field> fields) {
|
private static void doGetFields(Class<?> cl, List<Field> fields, Predicate<Field> predicate) {
|
||||||
if (cl == null || cl == Object.class) {
|
if (cl == null || cl == Object.class) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Field[] declaredFields = cl.getDeclaredFields();
|
Field[] declaredFields = cl.getDeclaredFields();
|
||||||
for (Field declaredField : declaredFields) {
|
for (Field declaredField : declaredFields) {
|
||||||
fields.add(declaredField);
|
if (predicate == null || predicate.test(declaredField)) {
|
||||||
|
fields.add(declaredField);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doGetFields(cl.getSuperclass(), fields);
|
doGetFields(cl.getSuperclass(), fields, predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Method> getAllMethods(Class<?> cl) {
|
public static List<Method> getAllMethods(Class<?> cl) {
|
||||||
@ -168,26 +175,26 @@ public class ClassUtil {
|
|||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Method> getAllMethods(Class<?> cl, Predicate<Method> tester) {
|
public static List<Method> getAllMethods(Class<?> cl, Predicate<Method> predicate) {
|
||||||
List<Method> methods = new ArrayList<>();
|
List<Method> methods = new ArrayList<>();
|
||||||
doGetMethods(cl, methods, tester);
|
doGetMethods(cl, methods, predicate);
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void doGetMethods(Class<?> cl, List<Method> methods, Predicate<Method> tester) {
|
private static void doGetMethods(Class<?> cl, List<Method> methods, Predicate<Method> predicate) {
|
||||||
if (cl == null || cl == Object.class) {
|
if (cl == null || cl == Object.class) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Method[] declaredMethods = cl.getDeclaredMethods();
|
Method[] declaredMethods = cl.getDeclaredMethods();
|
||||||
for (Method method : declaredMethods) {
|
for (Method method : declaredMethods) {
|
||||||
if (tester == null || tester.test(method)) {
|
if (predicate == null || predicate.test(method)) {
|
||||||
methods.add(method);
|
methods.add(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doGetMethods(cl.getSuperclass(), methods, tester);
|
doGetMethods(cl.getSuperclass(), methods, predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user