目录

一. 配置元素

1. select元素

2. insert元素

3. sql元素

4. resultMap元素

5. resultMap元素中的级联

(代码github)

一、映射器的配置元素

元素名称 描述 备注
select 查询语句 可以自定义参数,返回结果集
insert 插入语句 执行后返回一个整数,代表插入的条数
update 更新语句 执行后返回一个整数,代表更新的条数
delete 删除语句 执行后返回一个整数,代表删除的条数
sql 允许定义一部分SQL,然后在各个地方引用它 比如,一张表列名,一次定义,可以在多个SQL语句中使用
resultMap 用来描述从数据库结果集中来加载对象 它提供映射规则
cache 给定命名空间的缓存配置
cache-ref 其它命名空间缓存配置的引用

1. select元素----查询语句

元素 说明 备注
id 与Mapper的命名空间组合起来是唯一的,供MyBatis调用 如果命名空间和id结合起来不唯一,将抛出异常
parameterType 可以给出类的全类名,也可以给出别名,别名必须是MyBatis内部定义或者自定义 可以选择Java Bean、Map等简单的参数类型传递给SQL
resultType 定义类的全路径,在允许自动匹配的情况下,结果集将通过Java Bean的规范映射,不能和resultMap同时使用 常用的参数之一,比如统计总条数时可以把它的值设置为int
resultMap 它是映射集的引用,能提供自定义映射规则的机会 可以配置映射规则、级联、typeHandler等
flushCache 在调用SQL后,是否要求MyBatis清空之前查询本地缓存和二级缓存 取值为布尔值,true/false,默认值为false
useCache 启动二级缓存的开关,是否要求MyBatis将此次结果缓存 取值为布尔值,默认为true

1.1 简单的select元素应用

RoleMapper接口

Integer countUserByFirstName(String firstName);

RoleMapper.xml

<select id="countUserByFirstName" parameterType="string" resultType="int">select count(*) total from t_userwhere user_name like concat(#{firstName}, '%')
</select>

1.2 传递多个参数

  • 使用map接口传递参数(不推荐)
    首先,map是一个键值对应的集合,使用者要通过阅读它的键,才能明了其作用
    其次,使用map不能限定其传递的数据类型,业务性质不强,可读性差

  • 使用注解传递多个参数
    RoleMapper

    List<Role> findRoleByAnnotation(@Param("roleName") String rolename, @Param("note") String note);
    

    RoleMapper.xml

    <select id="findRoleByAnnotation" resultType="role">select id,role_name as roleNam, note from t_rolewhere role_name like concat('%', #{roleName}, '%')and note like concat('%', #{note}, '%')
    </select>
    
  • 通过Java Bean传递多个参数
    RoleMapper

    List<Role> findRolesByBean(RoleParams roleParams);
    

    RoleMapper.xml

    <select id="findRolesByBean" parameterType="cn.whc.March_30.entity.RoleParams" resultType="role">select id,role_name as roleNam, note from t_rolewhere role_name like concat('%', #{roleName}, '%')and note like concat('%', #{note}, '%')</select>
    
  • 混合使用
    例子,查询一个角色,通过角色名称和备注进行查询,同此还支持分页

     public class PageParams {private int start;private int limit;public int getStart() {return start;}public void setStart(int start) {this.start = start;}public int getLimit() {return limit;}public void setLimit(int limit) {this.limit = limit;}
    }
    
    List<Role> findByMix(@Param("params") RoleParams roleParams, @Param("page") PageParams pageParam);
    
    <select id="findByMix" resultType="role">select id,role_name as roleName, note from t_rolewhere role_name likeconcat ('%', #{params.roleName}, '%')and note like concat('%', #{params.note}, '%')limit #{page.start}, #{page.limit}</select>
    

1.3 使用resultMap映射结果集

<resultMap id="roleMap" type="cn.whc.March_30.entity.Role"><!--id代表主键, property代表POJO的属性名称, column代表SQL的列名--><id property="id" column="id"/><result property="roleName" column="role_name"/><result property="note" column="note"/></resultMap>

2.insert元素----插入语句

元素 说明 备注
id SQL编号,用来标识这条SQL 命名空间+id+databaseId唯一,否则将抛出异常
parameterType 可以给出类的全类名,也可以给出别名,别名必须是MyBatis内部定义或者自定义 可以选择Java Bean、Map等简单的参数类型传递给SQL
flushCache 是否刷新缓存,可以配置true/false,为true时,插入时会刷新一级和二级缓存,否则不刷新 取值为布尔值,true/false,默认值为true
useGeneratedKeys 是否启动JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键。 默认值为false
keyColumn 通过生成的键值设置表中的列名,这个设置仅在某些数据库中是必须的,当主键列不是表中的第一列时需要设置.如果是复合主键,需要把每一个名称用逗号隔开 不能和keyProperty连用
keyProperty 唯一标记一个属性,MyBatis会通过getGeneratedKeys的返回值,或者通过insert语句的selectKey子元素设置它的键值。如果是复合主键,要把每一个名称用逗号隔开 默认值为unset。不能和keyColumn连用

主键回填例子

<insert id="insertRole" parameterType="role" useGeneratedKeys="true" keyProperty="id">insert into t_role(role_name,note) values (#{roleName}, #{note})
</insert>

keyProperty代表将用哪个POJO的属性去匹配这个主键,这里是id,会用数据库生成的主键去赋值给这个POJO

3.sql元素

<sql id="roleCols">id,role_name,note
</sql><select id="getRole" parameterType="long" resultMap="roleMap">select <include refid="roleCols"/> from t_role where id = #{id}</select>

4.resultMap元素

作用: 定义映射规则、级联的更新、定制类型转换器等。resultMap定义的主要是一个结果集的映射关系,也就是SQL到Java Bean的映射关系定义,它也支持级联等特性。不支持更新或者保存

使用POJO存储结果集

<resultMap id="roleMap" type="cn.whc.March_30.entity.Role"><!--id代表主键, property代表POJO的属性名称, column代表SQL的列名--><id property="id" column="id"/><result property="roleName" column="role_name"/><result property="note" column="note"/>
</resultMap>

5.resultMap元素中的级联

级联是resultMap中的配置,分为三种

  • 鉴别器(discriminator):它是一个根据某些条件决定采用具体实现类级联的方案,比如体检表要根据性别去区分
  • 一对一(association):比如学生证和学生就是一种一对一的级联,雇员和工牌表也是一种一对一的级联
  • 一对多(collection):比如班主任和学生就是一种一对多的级联

例子

  • 以雇员表为中心
  • 雇员表和工牌表是一对一的级联关系
  • 雇员表和员工任务表是一对多的级联关系
  • 员工任务表和任务表是一对一的级联关系
  • 每个雇员都会有一个体检表,随着雇员表字段性别取值的不同,会有不同的关联表

一对一级联:雇员表通过id与工牌表(emp_id)关联

<!--工卡表信息--><association property="workCard" column="id" select="cn.whc.March_30.mapper.WorkCardMapper.getWorkCardByEmpId"/>

解析:雇员表通过编号(id)和工牌表(emp_id)关联,使用association元素,然后将结果返回给雇员POJO的属性workCard

一对一级联:雇员任务表通过任务编号(task_id)和任务表示关联

雇员任务表POJO

EmployeeTaskMapper.xml(雇员任务表的映射文件)

<mapper namespace="cn.whc.March_30.mapper.EmployeeTaskMapper"><resultMap id="EmployeeTaskMap" type="cn.whc.March_30.pojo.EmployeeTask"><id column="id" property="id"/><result column="emp_id" property="empId"/><result column="task_name" property="taskName"/><result column="note" property="note"/><!--雇员任务表和任务编号(task_id)和任务表示一对一级联关联--><!--property属性代表映射到POJO属性上--><!--分步查询:select配置是命名空间+SQL id的形式,可以指向对应Mapper的SQL,MyBatis就会通过对应的SQL将数据查询回来column代表雇员任务表SQL的列,用作参数传递给select属性指定的SQL,如果是多个参数,则需要用逗号隔开--><association property="task" column="task_id" select="cn.whc.March_30.mapper.TaskMapper.getTask"/></resultMap><select id="getEmployeeTaskByEmpId" resultMap="EmployeeTaskMap">select id,emp_id,task_name,task_id,note from t_employee_task where emp_id = #{empId}</select>
</mapper>

解析:雇员任务表通过任务编号(task_id)和任务表(id)表示关联,使用association元素

一对多级联:雇员通过雇员编号(id)和雇员任务表关联

<!--雇员任务表信息--><!--一对多级联,其select元素指向SQL,将通过雇员表中column指定的SQL字段作为参数进行传递然后将结果返回给雇员POJO的属性employeeTaskList--><collection property="employeeTaskList" column="id" select="cn.whc.March_30.mapper.EmployeeTaskMapper.getEmployeeTaskByEmpId" />

解析:collection元素:一对多级联,其select指向sql,通过column指定的SQL字段作为参数进行传递,然后将结果返回给雇员POJO的属性employeeTaskList

鉴别器:雇员表和体检表

SexEnum枚举类以及自定义SexTypeHandler(以后再补充,后续放在github)

 <resultMap id="employee" type="cn.whc.March_30.pojo.Employee"><id column="id" property="id"/><result column="real_name" property="realName"/><result column="sex" property="sex" typeHandler="cn.whc.March_30.typeHandler.SexTypeHandler"/><result column="birthday" property="birthday"/><result column="mobile" property="mobile"/><result column="email" property="email"/><result column="position" property="position"/><result column="note" property="note"/><!--工卡表信息--><association property="workCard" column="id" select="cn.whc.March_30.mapper.WorkCardMapper.getWorkCardByEmpId"/><!--雇员任务表信息--><!--一对多级联,其select元素指向SQL,将通过column指定的SQL字段作为参数进行传递然后将结果返回给雇员POJO的属性employeeTaskList--><collection property="employeeTaskList" column="id" select="cn.whc.March_30.mapper.EmployeeTaskMapper.getEmployeeTaskByEmpId" /><!--鉴别器,它的属性column代表使用哪个字段进行鉴别,这里是sex,子元素case用于区分,1则对应男,2则对应女--><discriminator javaType="long" column="sex"><case value="1" resultMap="maleHealthFormMapper"/><case value="0" resultMap="femaleHealthFormMapper"/></discriminator>
</resultMap><!--id为employee的resultMap 被femaleHealthFormMapper通过extends元素继承--><resultMap id="femaleHealthFormMapper" type="cn.whc.March_30.pojo.FemaleEmployee" extends="employee"><association property="femaleHealthForm" column="id" select="cn.whc.March_30.mapper.FemaleHealthFormMapper.getFemaleHealthForm"/></resultMap><resultMap id="maleHealthFormMapper" type="cn.whc.March_30.pojo.MaleEmployee" extends="employee"><association property="maleHealthForm" column="id" select="cn.whc.March_30.mapper.MaleHealthFormMapper.getMaleHealthForm"/></resultMap>

解析:discriminator元素:鉴别器,它的属性column代表使用哪个字段进行鉴别,这里的是sex,而它的子元素case,用于区分,类似于java的switch…case…语句。而resultMap属性表示采用哪个ResultMap去映射,比如sex=0,则使用femaleHealthFormMapper进行映射.
对于雇员体检表而言,id为employee的resultMap,被maleHealthFormMapper和femaleHealthFormMapper通过extends元素继承。

测试

N+1问题
上面的级联日志可以看出所有级联都加载出来了。但是会引发性能问题,比如作为一个雇员的管理者,只想要员工信息和员工任务信息,对于体检表和工牌的信息就是多余的。所以执行了几条毫无用处的SQL,导致数据库资源的损耗和系统性能的下降。
解决方法: Mybatis提供了延迟加载功能,一次性把常用的级联数据通过SQL直接查询出来,对于不常用的级联数据则等待要用时才取出

延迟加载
settings配置项

配置项 作用 配置选项说明 默认值
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。在特定关联关系中,可通过设置fetchType属性来覆盖该项的开关状态 true或false fasle
aggressiveLazyLoading 当启动时,对任意延迟属性的调用会时带有延迟加载属性的对象完整加载;反之,则每种属性按需加载 true或false 3.4.1版本后默认false

lazyLoadingEnabled是一个开关,决定开不开启延迟加载,默认值为false,则不开启延迟加载。正如上面例子,当获取员工信息时,所有信息都被加载进来。

测试1:lazyLoadingEnabled和aggressiveLazyLoading都为true

<settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="true"/>
</settings>
@Testpublic void test() {try {Logger logger = Logger.getLogger(AppTest.class);sqlSession = SqlSessionFactoryUtils.openSqlSession();EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);// 获取编号为1的雇员信息,但设置aggressiveLazyLoading为true后,由于任务表只与雇员任务表关联,没有被加载Employee employee = employeeMapper.getEmployee(1L);logger.info(employee.getBirthday());} catch (Exception e) {e.printStackTrace();} finally {if (sqlSession != null) {sqlSession.close();}}}


测试2:lazyLoadingEnabled为true;aggressiveLazyLoading为false
开启全局延迟,层级加载失效

<settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/>
</settings>


测试3:fetchType属性
上面的两种测试都是全局性配置,并不能解决我们的需求,我们希望加载雇员信息时,只加载雇员任务信息,因为层级加载会把工牌信息也加载进来。在MyBatis中使用fetchType属性,可以处理全局定义无法处理的问题

 <settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/></settings>
<collection property="employeeTaskList" column="id" select="cn.whc.March_30.mapper.EmployeeTaskMapper.getEmployeeTaskByEmpId" fetchType="eager" />


fetchType出现在级联元素(association、collection,注意:discriminator没有这个属性可配置)
属性值

  • eager:获得当前POJO后立即加载对应的数据
  • lazy:获得当前POJO后延迟加载对应的数据

另一种级联:采用连缀
SQL比较复杂;所需要的配置比之前复杂得多;一次性将所有的数据取出会造成内存的浪费。适用于比较简单且关联关系不多的场景下。

==============================================================================

TODO

这一节的内容还是挺多的,还没写完,后面的放在另一篇文章,这两天上课+晚睡觉,补午觉都到下午3 4点了,另外我的csdn网页版有时候就打不开(估计dns域名出问题了,坑了n次)
后面打算写一下idea命令行如何将项目推送到github中

【MyBatis】 ---- 映射器(接口+XML文件)相关推荐

  1. [MyBatis日记](3)映射器配置文件与映射器接口

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50659993 前一篇文章([MyBatis日 ...

  2. mybatis映射器用法

    mybatis映射器 映射器: 系统并没有给出固定且明确的概念,我的理解是:映射器实现了数据库和Java之间数据的交互. 映射器包含了增删改查和结果映射. mybatis映射器分类: mybatis映 ...

  3. [MyBatis] 通过代码配置+XML文件构建SqlSessionFactory

    [MyBatis] 通过代码配置+XML文件构建SqlSessionFactory 问题描述 版本说明 数据库 依赖 相关代码 XML文件: mybatis-config.xml FbPlayerMa ...

  4. mybatis映射器${}和#{}的区别

    mybatis映射器${}和#{}的区别 转载于:https://www.cnblogs.com/liyuchen/p/7850185.html

  5. Andriod:serializer序列化器生成xml文件

    serializer序列化器生成xml文件 目录 serializer序列化器生成xml文件 一.目录结构 二.类MainActivity 三.类:SMS 四.activity_main.xml 一. ...

  6. 扩展Mybatis,免配XML文件自动实现增删改和随意查询

    写在前面 以前有点懒,一直没有分享技术新的的习惯,这次居然有心情写点东西分享出来. 作为一个从很老很老的jdk就开始码java代码的码农,对Mybatis却一直都是一无所知,一直固守在Hibernat ...

  7. MyBatis映射器

    Mybatis配置概述 MyBatis的核心配置文件配置了很多影响MyBatis行为的信息,这些信息通常只会配置在一个文件中,并且不会轻易改动.另外,与Spring框架整合后,MyBatis的核心配置 ...

  8. mybatis入门实例(xml文件配置)

    官网:mybatis – MyBatis 3 | 简介 先做实例如下: 一:数据库建表(自己有的话可以不用创建) CREATE  TABLE  USER( id INT(20)  NOT  NULL  ...

  9. MyBatis中的Mapper.xml文件解析

    具体可以参见MyBatis中文开发文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html 我所述的主要有常用的几个标签和属性 一.parameterTy ...

最新文章

  1. 二进制包方式安装部署三节点k8s
  2. Discuz!$_G变量的使用方法
  3. 前端学习(1644):前端系列实战课程之上移和下移
  4. php 不允许外部访问,[日常] 解决mysql不允许外部访问
  5. MySQL的外键约束
  6. 沉浸式全息本是什么_够炫酷!联想全息教学设备,构建沉浸式教学场景
  7. 自监督学习在CV领域研究进展总结
  8. VedioCapture
  9. cad画流程图的插件_PIDCAD工艺流程图绘图软件
  10. python实现GIF,PNG,JPG图片转换报错解决
  11. 2019-02-04~2019-02-08
  12. Android仿人人客户端(v5.7.1)——个人主页(三)
  13. 同一工作组无法访问另一计算机,同一工作组无法访问如何解决【详解】
  14. 一个基于场景感应的android智能手机防丢失系
  15. windows,打印机无打印任务,仍不断打印
  16. 三防平板终端丨三防平板电脑丨三防平板如何应用在工业中?
  17. 钥匙串密码忘记了怎么办?如何在Mac上重置钥匙串密码
  18. astar插件下载 就行_PS模拟下雨插件下载 一键为照片添加下雨效果 小伙伴们收货啦...
  19. 基于HTML5的机器猫在线商城设计与实现
  20. jquery图片轮播思路

热门文章

  1. java getopt_getopt() 函数
  2. JDBC原理实现详解
  3. 如何找到相似Graph?DeepMind提出超越GNN的图匹配网络
  4. 【转】《新飞飞》网游服务器架构设计
  5. 告诉你MSN,QQ,网页总掉线该怎么办
  6. Git初始化本地仓库
  7. Configuration和AutoConfiguration
  8. vue项目npm报错npm ERR code ELIFECYCLE
  9. 2021年G3锅炉水处理考试报名及G3锅炉水处理考试资料
  10. flash反编辑软件大收集