一、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层接口方法名对应上;
不配置,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相同,就会报内存溢出异常。