springboot mybatis列舉配置(每次只需新增一個列舉類即可)
配置好的專案是怎麼樣的:
1、新建表、MGB生成Mapper.xml
2、新增列舉類 class XXXEnum implements DbEnum{…}
3、修改POJO實體屬性型別為XXXEnum
4、完成。
注:
這樣配置後,新增列舉是很簡單的,
且無需修改Mapper.xml,
resultMap|resultType都有效,
插入、查詢都自動轉換列舉型別。
實現方式:
1、myBatis的處理器typeHandler、自定義的列舉類介面DbEnum
2、springBoot配置handler(applicaiton.yml)
先來簡單的application.yml配置:
mybatis:
type-handlers-package: com.macro.mall.enums.config
然後是DbEnum:
public interface DbEnum<E extends Enum<?>, T> {
String getCode();
String getName();
}
最後是重點的TypeHandler:
TypeHandler,型別轉換器,在mybatis中用於實現java型別和JDBC型別的相互轉換。
我們自定義一個列舉型別轉換器,繼承TypeHandler
重點程式碼
// 1、此註解告訴mybatis遇到此PayWayEnum.class型別時,使用此處理器處理
@MappedTypes(value = {PayWayEnum.class})
public class UniversalEnumHandler<E extends Enum<E> & DbEnum> extends BaseTypeHandler<E> {
/**
* 2、value接收的Class[]型別,我們想讓實現DbEnum介面的列舉都自動轉換,不要麻煩的一一配置。
*/
static {
try {
// 3、MapperTypes是使用代理模式的,static塊中我們使用Proxy獲取並修改@MappedTypes(value = {})的value值
MappedTypes annotation = UniversalEnumHandler.class.getAnnotation(MappedTypes.class);
InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
memberValues.setAccessible(true);
Map values = (Map) memberValues.get(invocationHandler);
// 4、使用hutool工具包,獲取xxx包下,DbEnum的實現類。
Set<Class<?>> classes = ClassUtil.scanPackageBySuper("com.xxx.enums", DbEnum.class);
Class[] allDbEnums = classes.toArray(new Class[classes.size()]);
values.put("value", allDbEnums);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
詳細程式碼
package com.macro.mall.enums.config;
import cn.hutool.core.util.ClassUtil;
import com.macro.mall.enums.*;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.Set;
@MappedTypes(value = {})
public class UniversalEnumHandler<E extends Enum<E> & DbEnum> extends BaseTypeHandler<E> {
/**
* 自動載入列舉型別
* 動態修改@MappedTypes(value = {})的value值
*/
static {
try {
MappedTypes annotation = UniversalEnumHandler.class.getAnnotation(MappedTypes.class);
InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
memberValues.setAccessible(true);
Map values = (Map) memberValues.get(invocationHandler);
Set<Class<?>> classes = ClassUtil.scanPackageBySuper("com.xxx.enums", DbEnum.class);
Class[] allDbEnums = classes.toArray(new Class[classes.size()]);
values.put("value", allDbEnums);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
private final Class<E> type;
/**
* construct with parameter.
*/
public UniversalEnumHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, parameter.getCode());
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
String code = rs.getString(columnName);
return rs.wasNull() ? null : this.codeOf(this.type, code);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String code = rs.getString(columnIndex);
return rs.wasNull() ? null : this.codeOf(this.type, code);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String code = cs.getString(columnIndex);
return cs.wasNull() ? null : this.codeOf(this.type, code);
}
public <T extends Enum<?> & DbEnum> T codeOf(Class<T> enumClass, String code) {
T[] enumConstants = enumClass.getEnumConstants();
for (T t : enumConstants) {
if (t.getCode().equals(code)) {
return t;
}
}
return null;
}
}
最後放一個新增列舉的例子
package com.macro.mall.enums;
import com.macro.mall.enums.config.DbEnum;
import com.macro.mall.enums.config.Localisable;
public enum PayWayEnum implements DbEnum, Localisable {
ALI("ali", "支付寶"),
WX("wx", "微信支付"),
BANK("bank", "銀聯"),
TANSFER("tansfer", "轉賬"),
CASH("cash", "現金");
private String code;
private String name;
private PayWayEnum(String dbConstant, String messageKey) {
this.code = dbConstant;
this.name = messageKey;
}
@Override
public String getCode() {
return this.code;
}
@Override
public String getName() {
return this.name;
}
}
POJO實體
public class OrderPay {
private PayWayEnum payWay;
}
相關文章
- 列舉工具類
- java列舉類Java
- Java —— 列舉類(enum 類)Java
- Java(4)列舉類Java
- Java enum列舉類詳解 列舉的常見用法Java
- Java一個列舉類的2種實現。Java
- java_06列舉類Java
- JAVA(四)類集/列舉Java
- 【python】Enum 列舉類Python
- Java 列舉、JPA 和 PostgreSQL 列舉JavaSQL
- Day69.註解&列舉類的複習 -Java註解&列舉類Java
- 列舉和列舉的取值範圍
- Python元類與列舉類Python
- Rust 列舉類是什麼Rust
- Partial類、列舉、結構體結構體
- Java列舉Java
- Swift,列舉Swift
- Java列舉類與註解詳解——一篇文章讀懂列舉類與註解詳Java
- Java列舉類、註解和反射Java反射
- Python 列舉類原始碼解析Python原始碼
- 草根學Python(十一)列舉類Python
- C# 列舉與位列舉概述C#
- TypeScript 列舉enumTypeScript
- Java 列舉(enum)Java
- Swift-列舉Swift
- 自定義列舉
- TypeScript 列舉指南TypeScript
- Java列舉使用Java
- C#:列舉C#
- 列舉程式 (轉)
- 列舉比較
- 列舉型別型別
- Java的一個關於“星球”的列舉Java
- Java列舉類學習到進階Java
- Kotlin-17.列舉類(enum class)Kotlin
- Java列舉-通過值查詢對應的列舉Java
- Java 集合列舉泛型(一)Java泛型
- 一文了解java列舉Java