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;
|
||||
|
||||
import com.mybatisflex.core.handler.CompositeEnumTypeHandler;
|
||||
import com.mybatisflex.core.mask.MaskTypeHandler;
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
@ -51,7 +52,6 @@ public class ColumnInfo {
|
||||
protected String maskType;
|
||||
|
||||
|
||||
|
||||
public String getColumn() {
|
||||
return column;
|
||||
}
|
||||
@ -90,6 +90,10 @@ public class ColumnInfo {
|
||||
if (typeHandler != null) {
|
||||
return typeHandler;
|
||||
}
|
||||
//枚举
|
||||
else if (propertyType.isEnum()) {
|
||||
typeHandler = new CompositeEnumTypeHandler(propertyType);
|
||||
}
|
||||
//若用户未定义 typeHandler,而配置了数据脱敏,则使用脱敏的 handler 处理
|
||||
else if (StringUtil.isNotBlank(maskType)) {
|
||||
typeHandler = new MaskTypeHandler(maskType);
|
||||
|
||||
@ -173,6 +173,7 @@ public class TableInfoFactory {
|
||||
|
||||
//未配置 typeHandler 的情况下,只支持基本数据类型,不支持比如 list set 或者自定义的类等
|
||||
if ((column == null || column.typeHandler() == UnknownTypeHandler.class)
|
||||
&& !field.getType().isEnum()
|
||||
&& !defaultSupportColumnTypes.contains(field.getType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -144,22 +144,29 @@ public class ClassUtil {
|
||||
|
||||
public static List<Field> getAllFields(Class<?> cl) {
|
||||
List<Field> fields = new ArrayList<>();
|
||||
doGetFields(cl, fields);
|
||||
doGetFields(cl, fields, null);
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
Field[] declaredFields = cl.getDeclaredFields();
|
||||
for (Field declaredField : declaredFields) {
|
||||
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) {
|
||||
@ -168,26 +175,26 @@ public class ClassUtil {
|
||||
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<>();
|
||||
doGetMethods(cl, methods, tester);
|
||||
doGetMethods(cl, methods, predicate);
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
Method[] declaredMethods = cl.getDeclaredMethods();
|
||||
for (Method method : declaredMethods) {
|
||||
if (tester == null || tester.test(method)) {
|
||||
if (predicate == null || predicate.test(method)) {
|
||||
methods.add(method);
|
||||
}
|
||||
}
|
||||
|
||||
doGetMethods(cl.getSuperclass(), methods, tester);
|
||||
doGetMethods(cl.getSuperclass(), methods, predicate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user