Mybatis配置之typeAlias標簽的用法

Mybatis typeAlias標簽

在實際的工程之中,類的全限定名稱很長,當我們需要大量使用的時候,這非常不方便的,然而mybatis提供瞭typeAlias別名標簽供我們別名和自定義別名,然而在mybatis之中別名的註冊實際上由TypeAliasRegistry去定義,需要非常註意的是,在mybatis中名不區分大小寫的,這一點非常重要。

下面展示瞭mybatis自己自動初始化瞭一些別名:

那麼他是如何實現初始化別名的呢?

一般的是通過Configuration獲取TypeAliasRegistry類對象其中有一個getTypeAliasRegisry方法獲取別名,獲取之後就可以通過registerAlias方法對別名註冊瞭。

事實上Configuration對象也對一些常用的配置項配置瞭別名:

public class TypeAliasRegistry {
 
	//使用的HashMap來傳記錄,String為鍵或者屬性名稱,Class<?>則為鍵值或者為
	//屬性值。
  private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();
 
  /*
   * TypeAliasRegistry主要進行初始化別名的配置,
   */
  public TypeAliasRegistry() {
	  /*
	   * 初始化別名
	   * e.g. 調用registerAlias方法註冊別名
	   * 
	   */
    registerAlias("string", String.class); 
    registerAlias("byte", Byte.class);
    registerAlias("long", Long.class);
    registerAlias("short", Short.class);
    registerAlias("int", Integer.class);
    registerAlias("integer", Integer.class);
    registerAlias("double", Double.class);
    registerAlias("float", Float.class);
    registerAlias("boolean", Boolean.class);
 
    registerAlias("byte[]", Byte[].class);
    registerAlias("long[]", Long[].class);
    registerAlias("short[]", Short[].class);
    registerAlias("int[]", Integer[].class);
    registerAlias("integer[]", Integer[].class);
    registerAlias("double[]", Double[].class);
    registerAlias("float[]", Float[].class);
    registerAlias("boolean[]", Boolean[].class);
 
    registerAlias("_byte", byte.class);
    registerAlias("_long", long.class);
    registerAlias("_short", short.class);
    registerAlias("_int", int.class);
    registerAlias("_integer", int.class);
    registerAlias("_double", double.class);
    registerAlias("_float", float.class);
    registerAlias("_boolean", boolean.class);
 
    registerAlias("_byte[]", byte[].class);
    registerAlias("_long[]", long[].class);
    registerAlias("_short[]", short[].class);
    registerAlias("_int[]", int[].class);
    registerAlias("_integer[]", int[].class);
    registerAlias("_double[]", double[].class);
    registerAlias("_float[]", float[].class);
    registerAlias("_boolean[]", boolean[].class);
 
    registerAlias("date", Date.class);
    registerAlias("decimal", BigDecimal.class);
    registerAlias("bigdecimal", BigDecimal.class);
    registerAlias("biginteger", BigInteger.class);
    registerAlias("object", Object.class);
 
    registerAlias("date[]", Date[].class);
    registerAlias("decimal[]", BigDecimal[].class);
    registerAlias("bigdecimal[]", BigDecimal[].class);
    registerAlias("biginteger[]", BigInteger[].class);
    registerAlias("object[]", Object[].class);
 
    registerAlias("map", Map.class);
    registerAlias("hashmap", HashMap.class);
    registerAlias("list", List.class);
    registerAlias("arraylist", ArrayList.class);
    registerAlias("collection", Collection.class);
    registerAlias("iterator", Iterator.class); 
    registerAlias("ResultSet", ResultSet.class);
  }
 
  @SuppressWarnings("unchecked")
  // throws class cast exception as well if types cannot be assigned
  public <T> Class<T> resolveAlias(String string) {
    try {
      if (string == null) {
        return null;
      }
      // issue #748
      String key = string.toLowerCase(Locale.ENGLISH);
      Class<T> value;
      if (TYPE_ALIASES.containsKey(key)) {
        value = (Class<T>) TYPE_ALIASES.get(key);
      } else {
        value = (Class<T>) Resources.classForName(string);
      }
      return value;
    } catch (ClassNotFoundException e) {
      throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + e, e);
    }
  }
 
  /*
   * registerAlias方法輸入參數為包的路徑名稱,並且其要註冊的對應的類
   * 既可以僅通過包的完整名稱進行註冊,也可以通過提供包名和對應的類的註冊
   * 類型。
   * 方法1,通過提供包名稱進行註冊,默認的註冊為Object類
   */
  public void registerAliases(String packageName){
    registerAliases(packageName, Object.class);
  }
  
  /*
   * ResolverUtil用於定位,某一個類的路徑,可滿足任意條件類。兩個最常見的條件是
   * 一個類實現/繼承另一個類,或者用一個特定的註釋註釋它。但是,通過使用測試類,
   * 可以使用任意條件進行搜索。
   * 類加載器是用於定位所有位置(目錄和JAR文件)在類路徑中包含在一定的包裝類,
   * 然後加載這些類和檢查。默認情況下,類加載器使用的的線程可以由currentthread()。
   * getcontextclassloader()獲取其名稱, 但這可以通過調用setclassloader(ClassLoader)
   * 方法重寫
   */
  
  /*
   * 方法2:主要是利用ResolverUtil對提供的超類,和包名方式進行註冊
   */
 
  public void registerAliases(String packageName, Class<?> superType){
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
    for(Class<?> type : typeSet){
      // Ignore inner classes and interfaces (including package-info.java)
      // Skip also inner classes. See issue #6
    	//判斷是否為匿名類或者是接口,成員類即類中的嵌套類,是的話不註冊
      if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
        registerAlias(type);
      }
    }
  }
 
  /*
   * 方法3,僅提供註冊類型
   */
  public void registerAlias(Class<?> type) {
    String alias = type.getSimpleName();
    Alias aliasAnnotation = type.getAnnotation(Alias.class);
    if (aliasAnnotation != null) {
      alias = aliasAnnotation.value();
    } 
    registerAlias(alias, type);
  }
 
  public void registerAlias(String alias, Class<?> value) {
    if (alias == null) {
      throw new TypeException("The parameter alias cannot be null");
    }
    // issue #748
    String key = alias.toLowerCase(Locale.ENGLISH);
    if (TYPE_ALIASES.containsKey(key) && TYPE_ALIASES.get(key) != null && !TYPE_ALIASES.get(key).equals(value)) {
      throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(key).getName() + "'.");
    }
    TYPE_ALIASES.put(key, value);
  }
 
  public void registerAlias(String alias, String value) {
    try {
      registerAlias(alias, Resources.classForName(value));
    } catch (ClassNotFoundException e) {
      throw new TypeException("Error registering type alias "+alias+" for "+value+". Cause: " + e, e);
    }
  }
  
  /**
   * @since 3.2.2
   */
  public Map<String, Class<?>> getTypeAliases() {
    return Collections.unmodifiableMap(TYPE_ALIASES);
  } 
}

以上是mybatis中關於別名的類,其在org.apache.ibatis.type包裡面,還要註意某些已經註冊過的類別就不要重復定義瞭,這會引起mybatis 的運行錯誤,那麼我們如何實現自定義別名呢,

<typeAliases>
         <typeAlias alias="role" type="com.*.類名">
</typeAliases>

這樣可以定義一個別名瞭,如果需要很多的類需要註冊時,可以使用mybatis支持的掃描別名。

<typeAliases>
         <package name="com.">
</typeAliases>

這樣就會掃描指定的這個包,並將這個包中的類的第一個字母變為小寫字母的新名字作為別名,假如掃描的多個包中有同名稱的類,這時候就會產生異常,此時我們可以在pojo類添加Alias註解。

@Alias("User2")
public class User{
      ····
}

這樣就能夠導致不同的包中出現相同的類名而導致自動掃描的別名一樣造成的沖突,建議部分包名和類型名作為別名,可以有效進行區分。

Mybatis typeAlias配置

用3種方法實現typeAlias配置

1.定義別名:

<typeAliases>
     <typeAlias alias="User" type="cn.lxc.vo.User" />
</typeAliases>

2.掃描包方式:

<typeAliases>
     <package name="cn.lxc.vo" />
</typeAliases>

3.註解方式:

package cn.lxc.vo;
import org.apache.ibatis.type.Alias;
@Alias("User")
public class User {
    private int id;
    private String name;
    private int age;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: