mybait多表联查

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表:

  • mybait多表联查

  • \2. 部门表dept:

  • mybait多表联查

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.设置主键





上一篇:Docker命令基本使用


下一篇:Nedb 的简单学习