91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Mybatis中怎么自定義全局TypeHander

發布時間:2021-06-21 17:46:32 來源:億速云 閱讀:697 作者:Leah 欄目:大數據

本篇文章給大家分享的是有關Mybatis中怎么自定義全局TypeHander,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

1.首先創建List的TypeHander

public class ListTypeHandler extends BaseTypeHandler<List<String>> {


    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
        if (jdbcType == null) {
            ps.setString(i, StringUtils.collectionToCommaDelimitedString(parameter));
        } else {
            ps.setObject(i, parameter, jdbcType.TYPE_CODE);
        }
    }

    @Override
    public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String s = rs.getString(columnName);
        return s==null ? null : new ArrayList<String>(Arrays.asList(s.split(",")));
    }

    @Override
    public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String s = rs.getString(columnIndex);
        return s==null ? null : new ArrayList<>(Arrays.asList(s.split(",")));
    }

    @Override
    public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String s = cs.getString(columnIndex);
        return s==null ? null : new ArrayList<>(Arrays.asList(s.split(",")));
    }
}

首先繼承BaseTypeHandler,指定其泛型參數為我們需要轉換的java類型,BaseTypeHandler運用了模板方法模式,封裝了很多空值判斷,異常處理。說明一下:這里這個類型轉換器沒有指定具體的jdbcType,所以mybatis會自動判斷當java類型為List的時候就匹配這個這個轉換器。

2.然后注冊到Mybatis的TypeHandlerRegistry

注冊到TypeHandlerRegistry是為了全局自定義效果,如果不注冊,需要在Mapper,xml里面的resultMap去指定typeHander如:

<resultMap id="personMap" type="person">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex"/>
        <result property="hobbys" column="hobbys" typeHandler="com.sankuai.lkl.typeHandler.ListTypeHandler"/>
        <result property="date" column="data_time"/>
 </resultMap>

注冊的思路是直接在spring容器加載完bean的時候從容器里面取出TypeHandlerRegistry,然后注冊我們自定義的轉換器:

/**
 * @author chenzhicong
 * @time 2019/8/13 22:19
 * @description
 */
@Component
public class CustomTypeHandlerParser implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //從spring容器獲取sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = applicationContext.getBean(SqlSessionFactory.class);
        //獲取typeHandler注冊器
        TypeHandlerRegistry typeHandlerRegistry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
        //注冊List的typeHandler
        typeHandlerRegistry.register(List.class, ListTypeHandler.class);


    }
}

三、測試

@Test
  public void test() {
    UserJpaTest userJpaTest = new UserJpaTest();
    List<String> list = new ArrayList<>();
    list.add("phoneNumber1");
    list.add("phoneNumber2");
    userJpaTest.setPhoneNumber(list);
    userJpaTestMapper.insert(userJpaTest);

  }

四、效果

Mybatis中怎么自定義全局TypeHander

可以看到,在數據庫中已經把集合轉換為了逗號分隔的字符串。

五、進階-創建枚舉的TypeHandler

TypeHander還經常應用于枚舉與數據庫字符串的轉換策略,業務中,我們枚舉通常有三個變量,一個是給前端的展示字符,一個是存入數據庫的字符,另一個是我們在java系統的字符。為了讓數據庫只識別我們其中存入數據庫的字符,同時把數據庫中字符轉換為我們想要的枚舉。我們可以用自定義的轉換器來便利的實現。下面介紹下過程:

首先我們可以把所有枚舉抽象為一個接口。如下,我們抽象了所有枚舉為一個接口枚舉的EntityEnumIFace接口,接口的getDbCode方法為需要轉換的數據庫字符串,我們通過這個轉換器去處理這一類枚舉抽象的轉換:

public final class EntityEnumIFaceHandler<T extends Enum<T> & EntityEnumIFace> extends BaseTypeHandler<T> {
    private Class<T> type;

    public EntityEnumIFaceHandler(Class<T> type) {
        if (null == type) {
            throw new IllegalArgumentException("type參數不能為空");
        } else {
            this.type = type;
        }
    }
@Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, T t, JdbcType jdbcType) throws SQLException {
        if (jdbcType == null) {
            preparedStatement.setString(i, ((EntityEnumIFace)t).getDbCode());
        } else {
            preparedStatement.setObject(i, ((EntityEnumIFace)t).getDbCode(), jdbcType.TYPE_CODE);
        }

    }
    @Override
    public T getNullableResult(ResultSet resultSet, String s) throws SQLException {
        String value = resultSet.getString(s);
        return value == null ? null : valueOf(this.type, value);
    }
    @Override
    public T getNullableResult(ResultSet resultSet, int i) throws SQLException {
        String value = resultSet.getString(i);
        return value == null ? null : valueOf(this.type, value);
    }
    @Override
    public T getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        String value = callableStatement.getString(i);
        return value == null ? null : valueOf(this.type, value);
    }

    private static <E extends Enum<E> & EntityEnumIFace> E valueOf(Class<E> enumClass, String dbCode) {
       E[] enumConstants = enumClass.getEnumConstants();
        if (null != enumConstants) {
            for (E e : enumConstants) {
                if (e.getDbCode().equals(dbCode)) {
                    return e;
                }
            }
        }
        throw new BusinessException("ENUM_NOT_EXIST", enumClass.getSimpleName() + "枚舉中沒有" + dbCode, false);
    }
}

可能看了上面會奇怪,為什么前面定義的轉換器實例化沒有有參構造方法,這里卻定義了有參構造方法?這個實例化過程又是怎么樣的?別急,等下面我們再看,這里我們先將其注冊到容器,我們怎么注冊到容器勒?這里可以通過掃描指定包路徑然后獲取所有枚舉的class對象再用typeHandlerRegistry.register注冊到mybatis,如:

try {
            Set<Class<?>> set =  ClassUtil.listClass(BUSINESS_ENUM_PACKAGE);
            set.forEach(o->{
                if(EntityEnumIFace.class.isAssignableFrom(o.getClass())){
                    typeHandlerRegistry.register(o.getClass(),EntityEnumIFaceHandler.class);
                }
            });
        }catch (Exception e){
           log.error(e.getMessage(),e);
        }

其中ClassUtil.listClass方法邏輯就是掃描包路徑,然后用類加載器加載class文件獲取class對象。

我們可以看到這里和注冊ListTypeHandler沒有兩樣都是調用的同一個方法register(register(Class<?> javaTypeClass, Class<?> typeHandlerClass)),我們先進入這個方法看一看源碼,源碼調用了register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass),我們在進去getInstance方法看一看,怎么實例化的typeHandler,源碼如下:

public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
    if (javaTypeClass != null) {
      try {
        Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
        return (TypeHandler<T>) c.newInstance(javaTypeClass);
      } catch (NoSuchMethodException ignored) {
        // ignored
      } catch (Exception e) {
        throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
      }
    }
    try {
      Constructor<?> c = typeHandlerClass.getConstructor();
      return (TypeHandler<T>) c.newInstance();
    } catch (Exception e) {
      throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
    }
  }

以上就是Mybatis中怎么自定義全局TypeHander,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

临洮县| 保亭| 康马县| 华容县| 简阳市| 年辖:市辖区| 成都市| 巫溪县| 成武县| 新蔡县| 汤原县| 嵩明县| 遂川县| 黄大仙区| 五莲县| 海原县| 米易县| 松桃| 东城区| 江山市| 云安县| 大荔县| 台东县| 盖州市| 宁海县| 准格尔旗| 东乡县| 嘉兴市| 桃园市| 康马县| 平安县| 扶绥县| 砀山县| 青冈县| 唐山市| 博乐市| 肇庆市| 镇赉县| 定襄县| 夹江县| 汾阳市|