mybatis枚举自动转换(通用转换处理器实现)
From: https://blog.csdn.net/fighterandknight/article/details/51520595
前言
???????? 在上一篇博客,mybatis枚舉自動轉換實現,已經介紹自動轉換的實現步驟,并通過例子告訴大家如何實現枚舉的自動轉換了。 那么在博客的最后想到,定義一個萬能的枚舉轉換處理器,具體怎么實現呢,相信大神們也應該有思路了,使用泛型實現,沒錯,就是使用泛型實現,具體請看下面例子。
mybatis萬能枚舉轉換處理器
定義枚舉接口
為什么要定義枚舉的接口呢,定義接口的好處,其實主要目的是為了在萬能枚舉轉換器中方便泛型的使用,而且還可以規范枚舉類的實現。
??? package net.itaem.less;
??? ?
??? /**
???? * @author: Fighter168
???? */
??? public interface BaseEnum<E extends Enum<?>, T> {
?? ??? ?public T getValue();
?? ??? ?public String getDisplayName();
??? }
?
實現枚舉接口,定義枚舉
實現BaseEnum接口,定義PersonType枚舉
??? package net.itaem.less;
??? ?
??? import java.util.HashMap;
??? import java.util.Map;
??? ?
??? /**
???? * @author: Fighter168
???? */
??? public enum PersonType implements BaseEnum<PersonType, String>{
?? ??? ?student("1","學生"),
?? ??? ?teacher("2","教師");
?? ??? ?
?? ??? ?private String value;
?? ??? ?private String displayName;
?? ??? ?
?? ??? ?static Map<String,PersonType> enumMap=new HashMap<String, PersonType>();
?? ??? ?static{
?? ??? ??? ?for(PersonType type:PersonType.values()){
?? ??? ??? ??? ?enumMap.put(type.getValue(), type);
?? ??? ??? ?}
?? ??? ?}
?? ??? ?
?? ??? ?private PersonType(String value,String displayName) {
?? ??? ??? ? this.value=value;
?? ??? ??? ? this.displayName=displayName;
?? ??? ?}
?? ??? ?
?? ??? ?public String getValue() {
?? ??? ??? ?return value;
?? ??? ?}
?? ??? ?public void setValue(String value) {
?? ??? ??? ?this.value = value;
?? ??? ?}
?? ??? ?public String getDisplayName() {
?? ??? ??? ?return displayName;
?? ??? ?}
?? ??? ?public void setDisplayName(String displayName) {
?? ??? ??? ?this.displayName = displayName;
?? ??? ?}
?? ??? ?
?? ??? ?public static PersonType getEnum(String value) {
?? ??? ??? ?return enumMap.get(value);
?? ??? ?}
??? }
?
定義萬能枚舉轉換處理器
??? package net.itaem.handler;
??? ?
??? import java.sql.CallableStatement;
??? import java.sql.PreparedStatement;
??? import java.sql.ResultSet;
??? import java.sql.SQLException;
??? ?
??? import net.itaem.less.BaseEnum;
??? ?
??? import org.apache.ibatis.type.BaseTypeHandler;
??? import org.apache.ibatis.type.JdbcType;
??? ?
??? /**
???? * @author: Fighter168
???? */
??? public final class UniversalEnumHandler<E extends BaseEnum> extends BaseTypeHandler<E> {
??? ?
?? ??? ?private Class<E> type;
?? ??? ?private E [] enums;
?? ??? ?
??????? /**
???????? * 設置配置文件設置的轉換類以及枚舉類內容,供其他方法更便捷高效的實現
???????? * @param type 配置文件中設置的轉換類
???????? */
??????? public UniversalEnumHandler(Class<E> type) {
??????????? if (type == null)
??????????????? throw new IllegalArgumentException("Type argument cannot be null");
??????????? this.type = type;
??????????? this.enums = type.getEnumConstants();
??????????? if (this.enums == null)
??????????????? throw new IllegalArgumentException(type.getSimpleName()
??????????????????????? + " does not represent an enum type.");
??????? }
?? ??? ?
?? ??? ?@Override
?? ??? ?public void setNonNullParameter(PreparedStatement ps, int i, E parameter,
?? ??? ??? ??? ?JdbcType jdbcType) throws SQLException {
?? ??? ??? ?//BaseTypeHandler已經幫我們做了parameter的null判斷
?? ??? ???? ps.setObject(i,(String)parameter.getValue(), jdbcType.TYPE_CODE);
?? ??? ?}
??? ?
?? ??? ?@Override
?? ??? ?public E getNullableResult(ResultSet rs, String columnName)
?? ??? ??? ??? ?throws SQLException {
?? ??? ??? ?// 根據數據庫存儲類型決定獲取類型,本例子中數據庫中存放String類型
??????????? String i = rs.getString(columnName);
??????????? if (rs.wasNull()) {
??????????????? return null;
??????????? } else {
??????????????? // 根據數據庫中的value值,定位PersonType子類
??????????????? return locateEnumStatus(i);
??????????? }
?? ??? ?}
??? ?
?? ??? ?@Override
?? ??? ?public E getNullableResult(ResultSet rs, int columnIndex)
?? ??? ??? ??? ?throws SQLException {
?? ??? ??? ?// 根據數據庫存儲類型決定獲取類型,本例子中數據庫中存放String類型
??????????? String i = rs.getString(columnIndex);
??????????? if (rs.wasNull()) {
??????????????? return null;
??????????? } else {
??????????????? // 根據數據庫中的value值,定位PersonType子類
??????????????? return locateEnumStatus(i);
??????????? }
?? ??? ?}
??? ?
?? ??? ?@Override
?? ??? ?public E getNullableResult(CallableStatement cs, int columnIndex)
?? ??? ??? ??? ?throws SQLException {
?? ??? ??? ?// 根據數據庫存儲類型決定獲取類型,本例子中數據庫中存放String類型
??????????? String i = cs.getString(columnIndex);
??????????? if (cs.wasNull()) {
??????????????? return null;
??????????? } else {
??????????????? // 根據數據庫中的value值,定位PersonType子類
??????????????? return locateEnumStatus(i);
??????????? }
?? ??? ?}
??? ?
?? ??? ? /**
???????? * 枚舉類型轉換,由于構造函數獲取了枚舉的子類enums,讓遍歷更加高效快捷
???????? * @param value 數據庫中存儲的自定義value屬性
???????? * @return value對應的枚舉類
???????? */
??????? private E locateEnumStatus(String value) {
??????????? for(E e : enums) {
??????????????? if(e.getValue().equals(value)) {
??????????????????? return e;
??????????????? }
??????????? }
??????????? throw new IllegalArgumentException("未知的枚舉類型:" + value + ",請核對" + type.getSimpleName());
??????? }
??? }
?
測試
?????????? 接下來,我們就修改原來的例子(上一篇博客的例子:mybatis枚舉自動轉換實現),只需修改typeHandler,修改成
????? ??? ? <typeHandler handler="net.itaem.handler.UniversalHandler"
????? ??? ??? ? javaType="net.itaem.less.PersonType" jdbcType="CHAR"/>
然后我們再次運行測試用例,會發現,我們的查詢得到的結果還是一樣,這樣,我們就不需要為每一個枚舉創建一個Handler去自動轉換數據庫中的枚舉了。
?
自動掃描枚舉注冊想法
???????????? 做到這里,或許我們又想了,要是我們一個項目特別大,有幾十個甚至是上百個枚舉呢,那怎么辦,難道我要一個個在typeHandler里面去加,加一百幾十行?!個人覺得非常麻煩,影響我們的開發速度,so,能不能實現我們想要的像掃描下枚舉的所在的包目錄就可以注冊的枚舉做自動轉換呢?具體怎么實現?下篇博客我會教大家如何實現。
?
總結
以上是生活随笔為你收集整理的mybatis枚举自动转换(通用转换处理器实现)的全部內容,希望文章能夠幫你解決所遇到的問題。