成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用MyBatis簡(jiǎn)化枚舉類值的存儲(chǔ)和讀取

Bryan / 1948人閱讀

摘要:內(nèi)置的枚舉處理器為了處理上述遇到的問(wèn)題,內(nèi)置了兩種,分別是和。將使用枚舉實(shí)例的值序數(shù)值,從開(kāi)始來(lái)和枚舉類之間做轉(zhuǎn)換。比如有記錄顯式為全局指定在查詢時(shí),類變量將自動(dòng)賦值為,添加記錄時(shí)同理,數(shù)據(jù)庫(kù)值將存儲(chǔ)為其枚舉類實(shí)例序號(hào)。

場(chǎng)景描述

我們?cè)趯?shí)際場(chǎng)景中經(jīng)常會(huì)遇到需要將枚舉值存儲(chǔ)到數(shù)據(jù)庫(kù)中,或是將從數(shù)據(jù)庫(kù)中查詢到的值對(duì)應(yīng)到枚舉類上的情況。

比如表process大致定義如下:

-- ----------------------------
-- Table structure for process
-- ----------------------------
DROP TABLE IF EXISTS `process`;
CREATE TABLE `process` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `status` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

對(duì)應(yīng)實(shí)體類Process,大致定義如下:

public class Process{
    private int id;
    private String name;
    private ProcessStatus status;
    
    // 省略 getter setter toString 等
}

其中,枚舉類ProcessStatus,大致定義如下:

public enum ProcessStatus {
    RUNNING(100, "running"),
    BLOCKED(101, "blocked"),
    STOPPED(102, "stopped");

    private int code;
    private String desc;

    ProcessStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    
    // ...
}

如果此時(shí)我們想在存儲(chǔ)Process類時(shí)直接將ProcessStatus對(duì)應(yīng)成某種值,或者在查詢時(shí)直接將數(shù)據(jù)庫(kù)status字段值對(duì)應(yīng)成為ProcessStatus類,而不需要用硬編碼的方式做更多的轉(zhuǎn)換,我們可以考慮采用 MyBatis 提供的typeHandler。

MyBatis 內(nèi)置的枚舉處理器

為了處理上述遇到的問(wèn)題,MyBatis 內(nèi)置了兩種 typeHandler,分別是org.apache.ibatis.type.EnumTypeHandlerorg.apache.ibatis.type.EnumOrdinalTypeHandler

EnumTypeHandler

作為默認(rèn)的枚舉 typeHandler,EnumTypeHandler將使用枚舉實(shí)例名稱來(lái)和對(duì)應(yīng)的枚舉類之間做轉(zhuǎn)換。

比如process表有記錄:

id name status
1 first RUNNING

在查詢時(shí),Process類變量status將自動(dòng)賦值為ProcessStatus.RUNNING,添加記錄時(shí)同理,數(shù)據(jù)庫(kù)值將存儲(chǔ)為其枚舉類實(shí)例名稱(RUNNING/BLOCKED/STOPPED)。

EnumOrdinalTypeHandler

EnumOrdinalTypeHandler將使用枚舉實(shí)例的 ordinal 值(序數(shù)值,從0開(kāi)始)來(lái)和枚舉類之間做轉(zhuǎn)換。

比如process有記錄:

id name status
1 first 1

顯式為ProcessStatus全局指定 typeHandler:


    

在查詢時(shí),Process類變量status將自動(dòng)賦值為ProcessStatus.BLOCKED,添加記錄時(shí)同理,數(shù)據(jù)庫(kù)值將存儲(chǔ)為其枚舉類實(shí)例序號(hào)(0/1/2)。

混合使用

假如想在一處使用EnumTypeHandler,另外一處使用EnumOrdinalTypeHandler,可以在 mapped statement 中多帶帶指定 typeHandler。


  insert into process (id, name, status)
  values (#{id}, #{name}, #{status, typeHandler=org.apache.ibatis.type.EnumTypeHandler})


    
    
    

    
自定義枚舉處理器

回到我們的場(chǎng)景描述中來(lái),我們需要用枚舉實(shí)例的 code 值來(lái)對(duì)應(yīng)相應(yīng)的枚舉。此時(shí),系統(tǒng)內(nèi)置的兩個(gè)枚舉處理器便不能很好地完成我們的需求了,所以我們要自定義枚舉處理器。

實(shí)現(xiàn)方法

枚舉處理器也是處理器(typeHandler)的一種,關(guān)于自定義處理器的內(nèi)容,可以參考官方文檔。主要操作便是實(shí)現(xiàn)org.apache.ibatis.type.TypeHandler或繼承更為方便的org.apache.ibatis.type.BaseTypeHandler類。

我們選擇繼承BaseTypeHandler來(lái)完成工作,BaseTypeHandler需要實(shí)現(xiàn)4個(gè)方法:

public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException

用于定義設(shè)置參數(shù)時(shí),該如何把 Java 類型的參數(shù)轉(zhuǎn)換為對(duì)應(yīng)的數(shù)據(jù)庫(kù)類型

public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException

用于定義通過(guò)字段名稱獲取字段數(shù)據(jù)時(shí),如何把數(shù)據(jù)庫(kù)類型轉(zhuǎn)換為對(duì)應(yīng)的 Java 類型

public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException

用于定義通過(guò)字段索引獲取字段數(shù)據(jù)時(shí),如何把數(shù)據(jù)庫(kù)類型轉(zhuǎn)換為對(duì)應(yīng)的 Java 類型

public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException

用定義調(diào)用存儲(chǔ)過(guò)程后,如何把數(shù)據(jù)庫(kù)類型轉(zhuǎn)換為對(duì)應(yīng)的 Java 類型

由于「枚舉」是一個(gè)統(tǒng)稱,不像具體類型的處理器一樣可以使用多種方式來(lái)指定匹配的 Java 類型,所以按照官方文檔的做法,我們將使用指定泛型的方式來(lái)自定義枚舉構(gòu)造器(EnumTypeHanlderEnumOrdinalTypeHandler源代碼也是這么實(shí)現(xiàn)的),官方文檔示例:

//GenericTypeHandler.java
public class GenericTypeHandler extends BaseTypeHandler {

    private Class type;

      public GenericTypeHandler(Class type) {
        if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
      }
      ...
}
實(shí)現(xiàn)過(guò)程

為了更好完成自定義枚舉的工作,我們修改一下我們上面定義的枚舉ProcessStatus,使它實(shí)現(xiàn)一個(gè)通用接口。

public interface BaseEnum {
    int getCode();
}

public enum ProcessStatus implements BaseEnum{
    RUNNING(100, "running"),
    BLOCKED(101, "blocked"),
    STOPPED(102, "stopped");

    private int code;
    private String desc;

    ProcessStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    
    @Override
    public int getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }
}

然后再使用一個(gè)枚舉工作類來(lái)完成從枚舉 code 值獲得枚舉實(shí)例的工作:

public class EnumUtils {

    public static  & BaseEnum> T codeOf(Class enumClass, int code) {
        T[] enumConstants = enumClass.getEnumConstants();
        for (T t : enumConstants) {
            if (t.getCode() == code) {
                return t;
            }
        }
        return null;
    }
}

萬(wàn)事俱備,接下來(lái)完成自定義枚舉處理器:

import com.foo.BaseEnum;
import com.foo.EnumUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class EnumCodeTypeHandler & BaseEnum> extends BaseTypeHandler {

    private final Class type;

    public EnumCodeTypeHandler(Class 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.setInt(i, parameter.getCode());
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        int code = rs.getInt(columnName);
        return rs.wasNull() ? null : EnumUtils.codeOf(this.type, code);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int code = rs.getInt(columnIndex);
        return rs.wasNull() ? null : EnumUtils.codeOf(this.type, code);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        int code = cs.getInt(columnIndex);
        return cs.wasNull() ? null : EnumUtils.codeOf(this.type, code);
    }
}

在 mybatis-config.xml 中注冊(cè)枚舉處理器


    

假設(shè)數(shù)據(jù)庫(kù)process表有如下記錄:

id name status
1 first 101

ProcessMapper.java使用如下查詢:

@Select("select * from process where id=#{id}")
public Process findById(int id);

查詢結(jié)果 status 值將會(huì)對(duì)應(yīng)到枚舉實(shí)例 ProcessStatus.BLOCKED上。

查詢結(jié)果Process{id=1, name="first", status=BLOCKED}

設(shè)置默認(rèn)枚舉處理器

在 mybatis-config.xml 中為單個(gè)枚舉注冊(cè)枚舉處理器的方式在需要處理的枚舉數(shù)量增長(zhǎng)時(shí),會(huì)帶來(lái)很多不必要的工作量,根據(jù)官方文檔,我們可以在 configuration - settings節(jié)點(diǎn)下設(shè)置默認(rèn)枚舉處理器,沒(méi)有特殊指定處理器的枚舉都將默認(rèn)使用這個(gè)處理器。


        
說(shuō)明和參考資料

說(shuō)明:文中代碼測(cè)試基于 JDK 8,MyBatis 3.4.5。

參考資料:

MyBatis官方文檔之Configuration

如何在MyBatis中優(yōu)雅的使用枚舉,特別感謝這篇清晰明了的文章。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71158.html

相關(guān)文章

  • mybatis處理枚舉

    摘要:自帶對(duì)枚舉的處理類該類實(shí)現(xiàn)了枚舉類型和類型的相互轉(zhuǎn)換。而在具體中也需要使用屬性,如在處理到該位置時(shí),就會(huì)調(diào)用指定的處理類來(lái)處理枚舉類型。 mybatis自帶對(duì)枚舉的處理類 org.apache.ibatis.type.EnumOrdinalTypeHandler :該類實(shí)現(xiàn)了枚舉類型和Integer類型的相互轉(zhuǎn)換。 但是給轉(zhuǎn)換僅僅是將對(duì)應(yīng)的枚舉轉(zhuǎn)換為其索引位置,也就是ordinal(...

    caspar 評(píng)論0 收藏0
  • MyBatis 源碼分析系列文章導(dǎo)讀

    摘要:本文速覽本篇文章是我為接下來(lái)的源碼分析系列文章寫(xiě)的一個(gè)導(dǎo)讀文章。年該項(xiàng)目從基金會(huì)遷出,并改名為。同期,停止維護(hù)。符號(hào)所在的行則是表示的執(zhí)行結(jié)果。同時(shí),使用無(wú)需處理受檢異常,比如。另外,把寫(xiě)在配置文件中,進(jìn)行集中管理,利于維護(hù)。 1.本文速覽 本篇文章是我為接下來(lái)的 MyBatis 源碼分析系列文章寫(xiě)的一個(gè)導(dǎo)讀文章。本篇文章從 MyBatis 是什么(what),為什么要使用(why),...

    weizx 評(píng)論0 收藏0
  • mybatis動(dòng)態(tài)sql

    摘要:枚舉類型提供了提供了持久化的枚舉類型。假設(shè)表結(jié)構(gòu)的列,使用類型存儲(chǔ)或,對(duì)象使用枚舉類型標(biāo)識(shí)當(dāng)執(zhí)行語(yǔ)句時(shí),或會(huì)存儲(chǔ)到列,如果想要存儲(chǔ)的時(shí)枚舉值而不是枚舉名字,就需要配置類型處理器和提供了對(duì)和的內(nèi)檢支持,將映射為,將映射為數(shù)組。 mybatis中靜態(tài)sql語(yǔ)句有時(shí)不足以滿足用戶的需求,因此其提供了動(dòng)態(tài)sql標(biāo)簽。 IF標(biāo)簽 if標(biāo)簽通過(guò)條件測(cè)試,動(dòng)態(tài)插入sql片段,例如: an...

    anyway 評(píng)論0 收藏0
  • Mybatis學(xué)習(xí)筆記

    摘要:學(xué)習(xí)筆記有官方的中文開(kāi)發(fā)文檔并且針對(duì)使用者比較友好是一款優(yōu)秀的持久層框架,它支持定制化存儲(chǔ)過(guò)程以及高級(jí)映射。它只和配置有關(guān),存在的意義僅在于用來(lái)減少類完全限定名的冗余,為了簡(jiǎn)化中的書(shū)寫(xiě)。 Mybatis學(xué)習(xí)筆記 mybatis有官方的中文開(kāi)發(fā)文檔并且針對(duì)使用者比較友好:http://www.mybatis.org/mybatis-3/zh/ MyBatis 是一款優(yōu)秀的持久層框架,它支...

    jsyzchen 評(píng)論0 收藏0
  • Java 最常見(jiàn) 200+ 面試題全解析:面試必備(附答案)

    摘要:的簡(jiǎn)稱,運(yùn)行環(huán)境,為的運(yùn)行提供了所需環(huán)境。分割字符串,返回一個(gè)分割后的字符串?dāng)?shù)組。線程安全是線程安全的,而是非線程安全的。迭代器取代了集合框架中的,迭代器允許調(diào)用者在迭代過(guò)程中移除元素。 本文分為十九個(gè)模塊,分別是:?Java 基礎(chǔ)、容器、多線程、反射、對(duì)象拷貝、Java Web 、異常、網(wǎng)絡(luò)、設(shè)計(jì)模式、Spring/Spring MVC、Spring Boot/Spring Clou...

    hufeng 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<