真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Mybatis中怎么自定義全局TypeHander

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

創(chuàng)新互聯(lián)公司是一家專業(yè)提供邵東企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站設(shè)計(jì)、做網(wǎng)站、H5場(chǎng)景定制、小程序制作等業(yè)務(wù)。10年已為邵東眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。

1.首先創(chuàng)建List的TypeHander

public class ListTypeHandler extends BaseTypeHandler> {


    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List 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 getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String s = rs.getString(columnName);
        return s==null ? null : new ArrayList(Arrays.asList(s.split(",")));
    }

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

首先繼承BaseTypeHandler,指定其泛型參數(shù)為我們需要轉(zhuǎn)換的java類型,BaseTypeHandler運(yùn)用了模板方法模式,封裝了很多空值判斷,異常處理。說明一下:這里這個(gè)類型轉(zhuǎn)換器沒有指定具體的jdbcType,所以mybatis會(huì)自動(dòng)判斷當(dāng)java類型為L(zhǎng)ist的時(shí)候就匹配這個(gè)這個(gè)轉(zhuǎn)換器。

2.然后注冊(cè)到Mybatis的TypeHandlerRegistry

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


        
        
        
        
        
 

注冊(cè)的思路是直接在spring容器加載完bean的時(shí)候從容器里面取出TypeHandlerRegistry,然后注冊(cè)我們自定義的轉(zhuǎn)換器:

/**
 * @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注冊(cè)器
        TypeHandlerRegistry typeHandlerRegistry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
        //注冊(cè)List的typeHandler
        typeHandlerRegistry.register(List.class, ListTypeHandler.class);


    }
}

三、測(cè)試

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

  }

四、效果

Mybatis中怎么自定義全局TypeHander

可以看到,在數(shù)據(jù)庫中已經(jīng)把集合轉(zhuǎn)換為了逗號(hào)分隔的字符串。

五、進(jìn)階-創(chuàng)建枚舉的TypeHandler

TypeHander還經(jīng)常應(yīng)用于枚舉與數(shù)據(jù)庫字符串的轉(zhuǎn)換策略,業(yè)務(wù)中,我們枚舉通常有三個(gè)變量,一個(gè)是給前端的展示字符,一個(gè)是存入數(shù)據(jù)庫的字符,另一個(gè)是我們?cè)趈ava系統(tǒng)的字符。為了讓數(shù)據(jù)庫只識(shí)別我們其中存入數(shù)據(jù)庫的字符,同時(shí)把數(shù)據(jù)庫中字符轉(zhuǎn)換為我們想要的枚舉。我們可以用自定義的轉(zhuǎn)換器來便利的實(shí)現(xiàn)。下面介紹下過程:

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

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

    public EntityEnumIFaceHandler(Class type) {
        if (null == type) {
            throw new IllegalArgumentException("type參數(shù)不能為空");
        } 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  & EntityEnumIFace> E valueOf(Class 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);
    }
}

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

try {
            Set> 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對(duì)象。

我們可以看到這里和注冊(cè)ListTypeHandler沒有兩樣都是調(diào)用的同一個(gè)方法register(register(Class javaTypeClass, Class typeHandlerClass)),我們先進(jìn)入這個(gè)方法看一看源碼,源碼調(diào)用了register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass),我們?cè)谶M(jìn)去getInstance方法看一看,怎么實(shí)例化的typeHandler,源碼如下:

public  TypeHandler getInstance(Class javaTypeClass, Class typeHandlerClass) {
    if (javaTypeClass != null) {
      try {
        Constructor c = typeHandlerClass.getConstructor(Class.class);
        return (TypeHandler) 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) c.newInstance();
    } catch (Exception e) {
      throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
    }
  }

以上就是Mybatis中怎么自定義全局TypeHander,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


本文名稱:Mybatis中怎么自定義全局TypeHander
分享路徑:http://weahome.cn/article/gsgcii.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部