首页 > 技术文章 > MyBatis Mapper映射文件/主键回显/高级查询

ruhuanxingyun 2020-01-17 16:36 原文

一、Mapper映射文件(XML)

  1. mapper标签:最顶层的配置元素;

    A. namespace属性:指向Dao接口的全限定类名;

  2. resultMap标签:建立数据库表的列名与po类字段之间的映射关系,主要用于高级复杂的映射,如数据库表列名与类名对应不上;

    A. id元素:用于标识java对象的唯一性,不一定是数据库的主键;

    B. result元素:对应普通属性;

    C. collection元素:聚集元素用于处理“一对多”的关系;

       D. association元素:联合元素用于处理“一对一”的关系;

  3. select标签:SELECT查询语句;

    A. id属性(必须配置):命名空间中唯一标识符,与Dao层接口方法名对应上;

    A. parameterType属性:要传入语句的参数的全限定类名或别名,如果不配置,mybatis会通过ParameterHandler根据参数类型默认选择合适的typeHandler进行处理,它可以是int, short, long, string等类型,也可以是复杂类型(如对象);

    B. resultType属性(与resultMap二选一配置):用以指定返回类型,它可以是基本类型或对象或集合,若指定该属性就不可以用resultMap属性;

    C. resultMap属性(与resultType二选一配置):用于引用我们通过resultMap元素标签定义的映射类型;

    D. fetchSize属性:限制批量查询返回结果行数。

  4. insert标签:INSERT新增语句;

    A. useGeneratedKeys属性:是否开启主键回写;

    B. keyProperty属性:主键对应的属性名(实体中的属性名);

    C. statementType属性:STATEMENT、PREPARED、CALLABLE,默认值是PREPARED;

  5. update标签:UPDATE更新语句;

  6. delete标签:DELETE删除语句;

  7. sql标签:SQL片段,就是数据库字段;

  8. include标签:引入SQL片段;

  9. selectKey标签:为不支持自增的主键生成策略。

 可参考:Mybatis XML 映射器

 

二、主键回显

  1. 获取插入数据主键

    A. 用法:

     <insert keyProperty="主键字段" useGeneratedKeys="true"></insert>

     其中:keyColumn:主键列名(数据库表中的列名);

        keyProperty:主键对应的属性名(实体中的属性名);

          useGeneratedKeys:是否开启主键回写, 设置为true,mybatis会使用jdbc的getGeneratedKeys()方法来获取数据库内部生成得到主键。

    B. 实例:

复制代码
Message message = Message.builder()
                .userId(userId)
                .messageName(messageType.getName())
                .messageContent(messageContent)
                .build();
// 保存消息
messageMapper.saveMessage(message);
// 获取ID long messageId = message.getId(); <insert id="saveMessage" keyProperty="id" useGeneratedKeys="true"> insert into system_message (user_id, message_name, message_content, message_status, create_time) value (#{userId}, #{messageName}, #{messageContent}, 1, now()) </insert>
复制代码

    C. 错误示例:

      现象:主键回显总是1;

long messageId = messageMapper.saveMessage(message);

      原因:1是代表返回插入成功的行数;

      解决方式:获取ID正确方式是entity.getId(),如上图实例代码;

  2. 自定义主键规则 

 

三、联合查询和嵌套(递归)查询

  简介:查询树形结构数据常用联合查询(嵌套结果集)和嵌套(递归)查询,如菜单、部门等;

  1. 联合查询

    A. 定义:使用外连接查询;

    B. 特点:内存占用较大,但对数据库访问次数较少而导致消耗时间少;

  2. 嵌套查询

    A. 定义:是将原来多表查询中的联合查询语句拆成单个表的查询,再使用MyBatis的语法嵌套在一起嵌套查询使用时,先查询A表的信息,然后依赖A和B表的外键约束,再次查询B表对应到A表上的信息;

    B. 特点:内存使用较小,但需要多次访问数据库而导致消耗时间多,产生“N + 1”问题;

    C. 延迟加载:设置association或collection中属性fetchType="lazy";

  3. 递归查询实例

    A. VO类

package com.ruhuanxingyun.entity;

import lombok.Data;

import java.util.List;

/**
 * @description: 分组分支树
 * @author: ruphie
 * @date: Create in 2020/1/17 15:22
 * @company: ruhuanxingyun
 */
@Data
public class GroupHostVo {

    /**
     * ID
     */
    private Long id;

    /**
     * 父ID
     */
    private Long parentid;

    /**
     * 名称
     */
    private String name;

    /**
     * 子集
     */
    private List<GroupHostVo> children = new ArrayList();

}

    B. mapper.xml文件

  <!-- 级联查询返回模型 -->
    <resultMap id="groupHostMap" type="com.ruhuanxingyun.GroupHostVo">
        <id column="id" jdbcType="BIGINT" property="id"/>
        <result column="parentId" jdbcType="BIGINT" property="parentid"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <collection column="id" property="children" ofType="com.ruhuanxingyun.GroupHostVo" select="findHostListById"/>
    </resultMap>

    <!-- 级联查询分组数据 -->
    <select id="findGroupHostTree" resultMap="groupHostMap">
        select 0 as parentId, id, `name` from group where flag = 0 order by id asc
    </select>

    <!-- 级联查询分支数据 -->
    <select id="findHostListById" parameterType="long" resultType="com.ruhuanxingyun.GroupHostVo">
        select sensor_id as parentId, id, `name` from host where `type` = 2 and sensor_id = #{id} order by id asc
    </select>

    C. swagger数据展示

    D. 注意事项:查询子集数据时,select标签里是resultType,而不是resultMap,否则会无穷递归,如父子ID相同,就会报内存溢出异常。

  可参考: MyBatis 两种查询树形数据的方法详解

 

推荐阅读