博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)
阅读量:6293 次
发布时间:2019-06-22

本文共 10100 字,大约阅读时间需要 33 分钟。

摘要: 深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)   上篇文章《深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)》 介绍了properties与environments, 本篇...

  上篇文章《》 介绍了properties与environments, 本篇继续讲剩下的配置节点之一:typeAliases。 typeAliases节点主要用来设置别名,其实这是挺好用的一个功能, 通过配置别名,我们不用再指定完整的包名,并且还能取别名。

  例如: 我们在使用 com.demo.entity. UserEntity 的时候,我们可以直接配置一个别名user, 这样以后在配置文件中要使用到com.demo.entity. UserEntity的时候,直接使用User即可。

  就以上例为例,我们来实现一下,看看typeAliases的配置方法:

......

 

再写一段测试代码,看看有没生效:(我只写一段伪代码)

 

Configuration con = sqlSessionFactory.getConfiguration();Map
> typeMap = con.getTypeAliasRegistry().getTypeAliases();for(Entry
> entry: typeMap.entrySet()) { System.out.println(entry.getKey() + " ================> " + entry.getValue().getSimpleName());}

 

 

 

 

=======================================我是源码分割线==============================================

上面给大家简单介绍了typeAliases的用法, 接下来就看看Mybatis中的源码了:

老规矩,先从对xml的解析讲起:

/**  * 解析typeAliases节点  */ private void typeAliasesElement(XNode parent) {     if (parent != null) {       for (XNode child : parent.getChildren()) {         //如果子节点是package, 那么就获取package节点的name属性, mybatis会扫描指定的package         if ("package".equals(child.getName())) {           String typeAliasPackage = child.getStringAttribute("name");           //TypeAliasRegistry 负责管理别名, 这儿就是通过TypeAliasRegistry 进行别名注册, 下面就会看看TypeAliasRegistry源码           configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);         } else {           //如果子节点是typeAlias节点,那么就获取alias属性和type的属性值           String alias = child.getStringAttribute("alias");           String type = child.getStringAttribute("type");           try {             Class
clazz = Resources.classForName(type); if (alias == null) { typeAliasRegistry.registerAlias(clazz); } else { typeAliasRegistry.registerAlias(alias, clazz); } } catch (ClassNotFoundException e) { throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e); } } } } }

 

重要的源码在这儿:

TypeAliasRegistry:

public class TypeAliasRegistry {    //这就是核心所在啊, 原来别名就仅仅通过一个HashMap来实现, key为别名, value就是别名对应的类型(class对象)  private final Map
> TYPE_ALIASES = new HashMap
>(); /** * 以下就是mybatis默认为我们注册的别名 */ public TypeAliasRegistry() { 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); } /** * 处理别名, 直接从保存有别名的hashMap中取出即可 */ @SuppressWarnings("unchecked") public
Class
resolveAlias(String string) { try { if (string == null) return null; String key = string.toLowerCase(Locale.ENGLISH); // issue #748 Class
value; if (TYPE_ALIASES.containsKey(key)) { value = (Class
) TYPE_ALIASES.get(key); } else { value = (Class
) Resources.classForName(string); } return value; } catch (ClassNotFoundException e) { throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e); } } /** * 配置文件中配置为package的时候, 会调用此方法,根据配置的报名去扫描javabean ,然后自动注册别名 * 默认会使用 Bean 的首字母小写的非限定类名来作为它的别名 * 也可在javabean 加上注解@Alias 来自定义别名, 例如: @Alias(user) */ public void registerAliases(String packageName){ registerAliases(packageName, Object.class); } public void registerAliases(String packageName, Class
superType){ ResolverUtil
> resolverUtil = new ResolverUtil
>(); resolverUtil.find(new ResolverUtil.IsA(superType), packageName); Set
>> 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); } } } public void registerAlias(Class
type) { String alias = type.getSimpleName(); Alias aliasAnnotation = type.getAnnotation(Alias.class); if (aliasAnnotation != null) { alias = aliasAnnotation.value(); } registerAlias(alias, type); } //这就是注册别名的本质方法, 其实就是向保存别名的hashMap新增值而已, 呵呵, 别名的实现太简单了,对吧 public void registerAlias(String alias, Class
value) { if (alias == null) throw new TypeException("The parameter alias cannot be null"); String key = alias.toLowerCase(Locale.ENGLISH); // issue #748 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); } } /** * 获取保存别名的HashMap, Configuration对象持有对TypeAliasRegistry的引用,因此,如果需要,我们可以通过Configuration对象获取 */ public Map
> getTypeAliases() { return Collections.unmodifiableMap(TYPE_ALIASES); }}

 

由源码可见,设置别名的原理就这么简单,Mybatis默认给我们设置了不少别名,在上面代码中都可以见到。

好啦,本篇内容就是这么简单,到此为止。 下篇将继续讲解还没讲完的配置节点。

https://yq.aliyun.com/articles/52669

MyBatis一对多双向关联——MyBatis学习笔记之七

处理has-one关系需要用到association元素,

而处理has many关系则需要用到collection元素。
例如本例中,假设一名教师可同时指导多名学生,下面就来介绍如何使用collection元素来实现这种映射,
具体的任务是查询出教师及其指导的多个学生的信息(本示例源代码下载页面:)。

一、为Teacher实体增加相关属性

      为教师实体增加指导学生集合的属性如下:

private List
supStudents;//指导学生

 并为其增加setter和getter方法,这里略过

二、TeacherMapper接口

 为实现教师实体映射,应先创建映射器接口如下:

package com.abc.mapper;import com.abc.domain.Teacher;public interface TeacherMapper {public Teacher getById(int id);}

三、映射文件

为教师实体创建的映射文件如下:

由于教师、学生都有id、name、gender等属性,因此给教师的字段都起了别名-->
resultMap以命名空间名.resultMap的id的形式,引用studentResultMap。
需要注意的是,上面的select语句中学生的字段名/别名应与studentResultMap中的column属性一致-->

 相应地,学生实体的映射文件如下:

在工程的src\resources目录下新建子目录mappers,用来统一存放映射文件。为了能让MyBatis找到这些映射文件,修改其核心配置文件configuration.xml中的mappers元素如下:

注意:resources目录在工程编译前会被复制到classes目录下(详见工程生成文件build.xml中的copy-resources和compile这两个target),而classes目录会被ant添加到classpath中。

四、执行类

执行类为CollectionDemo,其内容如下:

package com.demo;import org.springframework.context.ApplicationContext;import com.abc.mapper.StudentMapper;import com.abc.mapper.TeacherMapper;import com.abc.domain.Teacher;import com.abc.domain.Student;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.List;public class CollectionDemo{private static ApplicationContext ctx;static{//在类路径下寻找resources/beans.xml文件ctx = new ClassPathXmlApplicationContext("resources/beans.xml");}public static void main(String[] args){//从Spring容器中请求映射器TeacherMapper mapper =(TeacherMapper)ctx.getBean("teacherMapper");//查询id为1的教师Teacher teacher = mapper.getById(1);if(teacher == null){System.out.println("未找到相关教师信息。");}else{//教师信息System.out.println("**********************************************");System.out.println("教师姓名:" + "  " + teacher.getName());System.out.println("教师职称:" + "  " + teacher.getTitle());System.out.println("**********************************************");System.out.println("指导学生信息:");//遍历指导的学生for(Student s : teacher.getSupStudents()){System.out.println("**********************************************");System.out.println( s.getName() + "  " + s.getGender() + "  " + s.getGrade()+ "  " + s.getMajor());//从学生端访问教师System.out.println("指导教师研究方向:" + s.getSupervisor().getResearchArea());}System.out.println("**********************************************");}}}

http://legend2011.blog.51cto.com/3018495/973579

 

转载于:https://www.cnblogs.com/softidea/p/6079950.html

你可能感兴趣的文章
PHP 7.1是否支持操作符重载?
查看>>
Vue.js 中v-for和v-if一起使用,来判断select中的option为选中项
查看>>
Java中AES加密解密以及签名校验
查看>>
定义内部类 继承 AsyncTask 来实现异步网络请求
查看>>
VC中怎么读取.txt文件
查看>>
如何清理mac系统垃圾
查看>>
企业中最佳虚拟机软件应用程序—Parallels Deskto
查看>>
Nginx配置文件详细说明
查看>>
怎么用Navicat Premium图标编辑器创建表
查看>>
Spring配置文件(2)配置方式
查看>>
MariaDB/Mysql 批量插入 批量更新
查看>>
ItelliJ IDEA开发工具使用—创建一个web项目
查看>>
solr-4.10.4部署到tomcat6
查看>>
切片键(Shard Keys)
查看>>
淘宝API-类目
查看>>
virtualbox 笔记
查看>>
Git 常用命令
查看>>
驰骋工作流引擎三种项目集成开发模式
查看>>
SUSE11修改主机名方法
查看>>
jdk6.0 + Tomcat6.0的简单jsp,Servlet,javabean的调试
查看>>