1. 动态Sql
1.1 动态Sql-where条件
1.1.1 业务需求
- 需求:根据对象中不为null的数据,充当where条件 进行查询
例子:根据属性来查询
-
User user = new User(); user.setId(null).setName(null).setAge(100).setSex("男") Sql: select * from demo_user where age = #{age} and sex = #{sex}
1.1.2 编辑测试类
-
@SpringBootTest public class TestMybatis2 { @Autowired 依赖注入 多态代理 private UserMapper2 userMapper; /** * 案例1: 测试动态sql */ @Test public void testDemo1(){ //pojo对象对应数据库中的查询表 User user = new User(); //根据字段设置查询条件 user.setAge(18).setSex("女"); //动态变化的数据 List<User> userList = userMapper.findUserList(user); System.out.println(userList); } }
1.1.3 编辑UserMapper接口
-
@Mapper public interface UserMapper2 { List<User> findUserList(User user); }
1.1.4 编辑UserMapper.xml映射文件
-
满足if判断,进行拼接sql,不满足则不拼接;
-
<?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.UserMapper2"> <!-- 动态Sql:根据对象中不为null的属性当作where条件 语法: 1.如果判断成立,则动态拼接条件 <if test="id !=null ">条件</if> 2.where标签 去除where后边多余的一个and/or --> <select id="findUserList" 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> </mapper>
1.2 动态Sql-set条件
1.2.1 编辑测试类
-
执行动态的更新操作
-
//根据对象中不为null的元素,充当set条件. where id=xxx @Test public void testDemo2(){ User user = new User(); //将表中id为231的信息进行替换 user.setId(231).setName("冬天").setAge(18); userMapper.updateUser(user); System.out.println("更新成功!!!"); }
1.2.2 编辑业务接口
-
void updateUser(User user);
1.2.3 编辑xml映射文件
-
标签可以自动的去除多余逗号
-
<!--根据对象中不为null的元素,充当set条件.--> <update id="updateUser"> 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>
1.3 动态Sql-choose、when、otherwise
1.3.1 业务需求
- 说明: 如果不想使用所有的条件可以使用choose 类似于java中的switch 语法:
- 如果name有值,则按照name查询,否则按照sex查询数据
1.3.2 编辑测试类
-
@Test public void testDemo3(){ User user = new User(); user.setName(null).setAge(null).setSex("女"); List<User> userList = userMapper.findUserByNS(user); System.out.println(userList); }
-
1.3.3 编辑业务接口
-
List<User> findUserByNS(User user);
1.3.4 编辑Mapper 映射文件
-
类似java中if elseif else的关系;
-
<select id="findUserByNS" 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>
1.4 resultMap
1.4.1 需求说明
- 当表中的字段与POJO中的属性名称不一致时,需要使用resultMap的方式进行映射.
1.4.3 创建POJO对象
-
@Data @Accessors(chain = true) @NoArgsConstructor @AllArgsConstructor public class Dog implements Serializable { private Integer dogId; private String dogName; private Integer age; }
1.4.4 测试结果
- 表中的字段名称与对象中的属性名称不一致. 结果:数据不能映射.
1.4.4 关于返回属性的说明
- resultType : 只能支持字段名称与属性的名称一致时才能自动映射.
- resultMap: 可以支持 任意类型的映射 万能的结构
1.4.5 编辑测试类
-
@Test public void testDog(){ List<Dog> dogList = dogMapper.findAll(); System.out.println(dogList); }
-
1.4.6 编辑Mapper接口
-
@Mapper public interface DogMapper { List<Dog> findAll(); }
1.4.7 编辑Mapper 映射文件
-
就是为了让pojo对象中的属性与表中属性名进行匹配
-
<?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"> //一个接口对应一个xml文件 <mapper namespace="com.jt.mapper.DogMapper"> <select id="findAll" resultMap="dogRM"> select * from dog </select> <resultMap id="dogRM" type="Dog"> <!--ID:代表主键--> <id column="dog_id" property="dogId"/> <!--结果集--> <result column="dog_name" property="dogName"/> <!--<result column="age" property="age"/>--> </resultMap> </mapper>
1.5 开启驼峰规则映射
-
说明: 在业务中经常出现该现象. 字段 user_id 属性:userId 属性和字段有驼峰映射规则.但是采用resultType的方式进行映射.则不能正常赋值.
-
解决方案:
-
1**.resultMap** :步骤比较繁琐
-
2.resultType+开启驼峰映射规则(配置yml文件)
-
mybatis: #定义别名包 type-aliases-package: com.jt.pojo #将所有的映射文件全部加载 mapper-locations: classpath:/mappers/*.xml #开启驼峰映射 configuration: map-underscore-to-camel-case: true
-
2 Mybatis 关联查询
2.1 常见关联关系
- 一对一 一个员工对应一个部门
- 一对多 一个部门对应多个员工
- 多对多:
- 双向的一对多 1.一个老师对应多个学生,2.一个学生对应多个老师
2.2 创建数据表
-
说明: 一个员工emp对应一个部门dept
-
1.emp表:
-
\2. 部门表dept:
2.3 关联查询Sql
2.3.1 笛卡尔积的方式
特点: 只获取2张表的 交集
-
SELECT * FROM emp,dept WHERE emp.dept_id = dept.dept_id
2.3.2 连接查询
分类: 1.左连接 2.内连接 3.右连接
-
/*左连接 emp表当作主表 */ SELECT * FROM emp LEFT JOIN dept ON emp.dept_id = dept.dept_id
2.4 封装关联关系
2.4.1 封装Emp对象
-
注意:关联关系: 一个员工对应一个部门
-
在员工类中封装部门的对象;
-
import java.io.Serializable; @Data @Accessors(chain = true) @NoArgsConstructor @AllArgsConstructor public class Emp implements Serializable { private Integer id; private String name; private Integer age; //关联关系: 一个员工对应一个部门 private Dept dept; //private Integer deptId; }
2.4.2 封装Dept对象
-
注意:关联 一个部门下有多个员工
-
在部门的类中创建一个list集合存放员工对象;
-
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; }
2.5 一对一封装
2.5.1 编辑测试类
-
通过迪卡尔积查询2张表的信息
-
import java.util.List; @SpringBootTest public class TestMybatis3 { @Autowired private EmpMapper empMapper; @Test public void testOneToOne(){ List<Emp> empList = empMapper.findAll(); System.out.println(empList); } }
2.5.2 编辑测试接口
-
@Mapper public interface EmpMapper { List<Emp> findAll(); }
2.5.3 编辑xml映射文件
-
注意:主键必填项
-
1.如果进行关联操作,使用resultMap
-
2.如果是多表关联操作,则不允许出现重名字段.否则映射失败.
-
所以在连接查询时,不能使用 select *
-
需要使用 SELECT emp.*,dept.dept_name 来去除一个dept.dept_id
-
3.如果有关联映射: 则需要添加自动映射的开关autoMapping="true"
-
该注解只对当前对象有效 如果有多个对象,则需要添加多次
-
4.一对一关联封装 association标签
-
必须指定属性的类型 javaType属性
-
对应的是Emp类中的:private Dept dept;
-
<?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"> <!-- 规则: 1.如果操作单表 一般使用resultType 2.如果进行关联操作,使用resultMap 3.如果是多表关联操作,则不允许出现重名字段.否则映射失败. --> <select id="findAll" resultMap="empRM"> SELECT emp.id,emp.name,emp.age,dept.dept_id, dept.dept_name FROM emp,dept WHERE emp.dept_id = dept.dept_id </select> <!-- 关于自动映射规则: 1.没有关联映射时: 如果属性和字段同名,则可以省略不写. 2.如果有关联映射: 则需要添加自动映射的开关autoMapping="true" 该注解只对当前对象有效 如果有多个对象,则需要添加多次 --> <resultMap id="empRM" type="Emp" autoMapping="true"> <!--主键是必填项--> <id column="id" property="id"/> <!-- 知识点: 1.一对一关联封装 association标签 2.必须指定属性的类型 javaType属性 3.autoMapping="true" 自动映射 --> <association property="dept" javaType="Dept" autoMapping="true"> <!--主键必填项--> <id column="dept_id" property="deptId"/> <!--由于一起开启驼峰规则映射.所以下列的操作可以省略--> <!--<result column="dept_name" property="deptName"/>--> </association> </resultMap> </mapper>
2.5 一对多封装
-
需求:查询每个部门员工
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M8dBcZLf-1645617048586)(C:\Users\86131\Desktop\学习图库\左连接.png)]
-
SELECT dept.dept_name,emp.* FROM dept LEFT JOIN emp ON emp.dept_id=dept.dept_id
2.5.1 关联说明
-
一个部门下,对应多个员工, 主对象是Dept
-
//一个部门存在多个员工 一对多的关系 List<Emp> emps;
2.5.2 编辑测试类
-
@Test public void test2(){ List<Dept> list=deptMapper.findAll(); System.out.println(list); }
2.5.3 编辑测试接口
-
@Mapper public interface DeptMapper { List<Dept> findAll(); }
2.5.4 编辑xml映射文件
-
步骤
-
1.一个接口对应一个映射文件
-
2.id代表方法名 resultMap 名称随意
-
3.type 代表List list=deptMapper.findAll();方法中返回的对象
-
4.必须设置主键
-
5.对于一对多的封装 需要使用collection标签
-
6.设置主键
-
1.一个接口对应一个映射文件 <mapper namespace="com.jt.mapper.DeptMapper"> 2.id代表接口中方法名 resultMap 名称随意 <select id="findAll" resultMap="deptRM"> SELECT dept.dept_name,emp.* FROM dept LEFT JOIN emp ON emp.dept_id=dept.dept_id </select> 3.type 代表List<Dept> findAll();方法中返回的对象 <resultMap id="deptRM" type="Dept" autoMapping="true"> 4.必须设置主键 <id column="dept_id" property="deptId"></id> 5.对于一对多的封装 需要使用collection标签 property和ofType 对应的是Dept类中定义的:List<Emp> emps; <collection property="emps" ofType="Emp" autoMapping="true"> 6.设置主键 <id column="id" property="id"></id> </collection> </resultMap> </mapper>
t LEFT JOIN emp
ON emp.dept_id=dept.dept_id
3.type 代表List findAll();方法中返回的对象
4.必须设置主键
5.对于一对多的封装 需要使用collection标签
property和ofType 对应的是Dept类中定义的:List emps;
6.设置主键