大家好,又见面了,我是你们的朋友全栈君。
Mybatis 动态SQL
一 .动态SQL
数组 array 使用foreach 标签
<!-- mybatis的集合操作
知识点: 如果遇到集合参数传递,需要将集合遍历
标签: foreach 循环遍历集合
标签属性说明:
1.collection 表示遍历的集合类型
1.1 数组 关键字 array
1.2 List集合 关键字 list
1.3 Map集合 关键字 Map中的key
2. open 循环开始标签
close 循环结束标签 包裹循环体
3. separator 分割符
4. item 当前循环遍历的数据的变量
-->
<select id="findIn" resultType="User">
select * from demo_user where id in
<foreach collection="array" open="(" close=")"
separator="," item="id">
#{id}
</foreach>
</select>
集合 collection 使用foreach 标签
<select id="findInList" resultType="User">
select * from demo_user where id in
<foreach collection="list" open="(" close=")"
separator="," item="id">
#{id}
</foreach>
</select>
Map集合操作
/**
* 需求:
* 查询id=1,3,5,6,7 并且sex="男"的用户
* Sql:
* select * from demo_user where id in (1,3....)
* and sex = "男"
*/
动态 sql-where-if
业务需求
说明: 用户传递了一个user对象, 要求根据user中不为null的属性查询数据.
<!-- 动态Sql语句
核心思想: 自动判断是否为null,
如果为null,该字段不参与sql
动态Sql规则:
1. <if test="写判断条件,可以直接获取属性值"></if>
true: 会拼接 字段条件
false: 不会拼接字段条件
2. 多余的关键字
由于动态sql拼接必然会导致多余的and 或者 or
3. where标签说明 可以去除 where后边多余的and 或者 or
-->
<select id="findSqlWhere" resultType="User">
select * from demo_user
<where>
<if test="id != null"> id = #{id}</if>
<if test="name != null">and name = #{name}</if>
<if test="age != null ">and age = #{age}</if>
<if test="sex != null ">and sex = #{sex}</if>
</where>
</select>
sql-set-if
业务需求
需求: 实现用户数据修改, 根据对象中不为null的数据完成修改操作
<!--
set标签用法: 去除set条件中多余的,号
-->
<update id="updateSqlSet">
update demo_user
<set>
<if test="name !=null"> name=#{name}, </if>
<if test="age !=null"> age = #{age}, </if>
<if test="sex !=null"> sex = #{sex} </if>
</set>
where id = #{id}
</update>
动态 sql-分支结构语法
业务需求
需求: 根据属性查询数据, 如果name有值 按照name查询,否则按照年龄查询,如果name,age都没有 按照sex查询
需求分析:
if(name !=null ){
name = #{name}
}else if( age !=null){
age = #{age}
}else{
sex = #{sex}
}
<!--
如果只需要一个条件有效,则使用分支结构用法.
-->
<select id="findChoose" resultType="User">
select * from demo_user
<where>
<choose>
<when test="name !=null">
name = #{name}
</when>
<when test="age !=null">
age = #{age}
</when>
<otherwise>
sex = #{sex}
</otherwise>
</choose>
</where>
</select>
二. Mybatis关联查询
创建新项目
选择项目
编辑POM.xml文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入插件lombok 自动的set/get/构造方法插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--mybatis依赖包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!--jdbc依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
复制配置文件
创建表
创建员工表
emp_id int 主键自增
emp_name varchar(40)
dept_id int
表数据结构
添加内容
创建部门表
dept部门表
dept_id int 主键自增
dept_name varchar(40)
表数据结构
表数据
创建POJO对象
Emp
package com.jt.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class Emp implements Serializable {
private Integer empId;
private String empName;
//关联关系 1: 一个员工对应一个部门
private Dept dept;
}
Dept
package com.jt.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {
private Integer deptId;
private String deptName;
//一个部门对应多个员工
private List<Emp> emps;
}
完成一对一封装
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jt.mapper.EmpMapper">
<!-- 一对一关联查询 -->
<select id="findAll" resultMap="empRM">
select e.emp_id,e.emp_name,
d.dept_id,d.dept_name
from emp e,dept d
where e.dept_id = d.dept_id
</select>
<!--3.完成一对一封装
固定用法:
1.association: 将结果集封装为单独的对象 dept
2.property 需要封装的属性名称
3.javaType 固定写法: 属性的类型
-->
<resultMap id="empRM" type="Emp">
<!--1.主键字段 -->
<id property="empId" column="emp_id"></id>
<!--2.映射其它属性字段-->
<result property="empName" column="emp_name"></result>
<association property="dept" javaType="Dept">
<!--3.完成dept对象的封装-->
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
</association>
</resultMap>
</mapper>
一对多
业务场景
说明: 一个部门有多个员工
/*内连接的另外的一种表现形式.*/
SELECT d.dept_id,d.dept_name,e.emp_id,e.emp_name
FROM dept d,emp e
WHERE e.dept_id = d.dept_id
完成一对多封装
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jt.mapper.DeptMapper">
<select id="findAll" resultMap="deptRM">
select d.dept_id,d.dept_name,e.emp_id,e.emp_name
from dept d,emp e
where e.dept_id = d.dept_id
</select>
<!--Mybatis的映射,一般都是一级封装 -->
<resultMap id="deptRM" type="Dept">
<!--指定主键-->
<id column="dept_id" property="deptId"/>
<!--封装其它的属性字段-->
<result column="dept_name" property="deptName"/>
<!--封装集合 属于同一个部门下的员工,封装到一个集合中 -->
<collection property="emps" ofType="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
</collection>
</resultMap>
</mapper>
接口文档说明
-
请求路径 /rights/getRightsList
-
请求类型 GET
-
请求参数 无
-
响应数据 SysResult对象
status |
状态信息 |
200表示服务器请求成功 201表示服务器异常 |
msg |
服务器返回的提示信息 |
可以为null |
data |
服务器返回的业务数据 |
返回权限List集合 |
参数名称 |
参数说明 |
备注 |
响应数据如图所示
父子关系封装/Sql语句写法
要求: 查询所有一级菜单和一级菜单所对应的二级菜单 要求关联查询
SELECT p.id,p.name,p.parent_id,p.path,p.level,p.created,p.updated,
c.id c_id,c.name c_name,c.parent_id c_parent_id,c.path c_path,
c.level c_level,c.created c_created,c.updated c_updated
FROM
rights p
LEFT JOIN
rights c
ON
c.parent_id = p.id
WHERE p.parent_id = 0
编辑RightsController
@RestController
@CrossOrigin
@RequestMapping("/rights")
public class RightsController {
@Autowired
private RightsService rightsService;
/**
* 查询一级二级数据
* URL: /rights/getRightsList
* 参数: 无
* 返回值: SysResult(List<Rights>)
*/
@GetMapping("/getRightsList")
public SysResult getRightsList(){
List<Rights> rights = rightsService.getRightsList();
return SysResult.success(rights);
}
}
sql
<mapper namespace="com.jt.mapper.RightsMapper">
<select id="getRightsList" resultMap="rightsRM">
select p.id,p.name,p.parent_id,p.path,p.level,p.created,p.updated,
c.id c_id,c.name c_name,c.parent_id c_parent_id,c.path c_path,
c.level c_level,c.created c_created,c.updated c_updated
from
rights p
left join
rights c
on
c.parent_id = p.id
where p.parent_id = 0
</select>
<resultMap id="rightsRM" type="Rights" autoMapping="true">
<id column="id" property="id"/>
<!--一对一封装子级菜单List集合-->
<collection property="children" ofType="Rights">
<!--封装主键ID-->
<id column="c_id" property="id"/>
<result column="c_name" property="name"/>
<result column="c_parent_id" property="parentId"/>
<result column="c_path" property="path"/>
<result column="c_level" property="level"/>
<result column="c_created" property="created"/>
<result column="c_updated" property="updated"/>
</collection>
</resultMap>
</mapper>
编辑RightsService
Mybatis的子查询
子查询原理
矛盾点:
1. 如果想简化Sql,则映射文件肯定复杂.
2. 如果想简化映射文件, 则Sql语句复杂.
案例说明: 需求 简化Sql, 那么映射文件复杂.
<!--
子查询本质特点: 将多表关联查询, 转化个多个单表查询.
-->
<select id="selectChildren" resultMap="cRM">
select * from dept
</select>
<!--子查询:
1.标签: select 进行二次查询
2.关联字段信息: column="dept_id" 将字段的值作为参数 传递给子查询
-->
<resultMap id="cRM" type="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<!--数据集合封装-->
<collection property="emps" ofType="Emp" select="findEmp" column="dept_id">
</collection>
</resultMap>
<select id="findEmp" resultMap="empRM">
select * from emp where dept_id = #{dept_id}
</select>
<resultMap id="empRM" type="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
</resultMap>
驼峰映射
<!--查询用户信息 开启驼峰映射规则
resultType:
1.适用与单表查询,同时要求属性名称与字段相同.
2.如果属性与字段满足驼峰命名规则,开启驼峰映射之后,
可以使用resultType
resultMap:
1.如果字段不一致时使用
2.多表关联查询时使用.
3.如果开启了驼峰映射规则, 则自动映射的属性可以省略,最好标识主键
4.如果使用驼峰规则映射时,需要映射封装对象时(一对一/一对多),默认条件下.驼峰规则失效.
可以使用: autoMapping="true" 要求开启驼峰映射.
5.默认条件下 一对一,一对多不会自动完成驼峰规则映射.
需要配置 autoMapping="true"才能自动映射
-->
<select id="getAll" resultMap="getEmpMap">
select e.emp_id,e.emp_name,
d.dept_id,d.dept_name
from emp e,dept d
where e.dept_id = d.dept_id
</select>
<resultMap id="getEmpMap" type="Emp" autoMapping="true">
<id column="emp_id" property="empId"/>
<!--其它属性自动映射-->
<!--实现部门映射-->
<association property="dept" javaType="Dept" autoMapping="true">
<id column="dept_id" property="deptId"/>
</association>
</resultMap>
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/152515.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...