【后端结合】新程序猿笔记Day10

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 编辑测试类

package com.jt;

import com.jt.mapper.UserMapper;
import com.jt.mapper.UserMapper2;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
public class TestMybatis2 {

    @Autowired
    private UserMapper2 userMapper;

    /**
     * 案例1: 测试动态sql
     */
    @Test
    public void testDemo1(){
        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映射文件

<?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();
        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中的switchh或者if else语句 语法:
如果name有值,则按照name查询,否则按照sex查询数据.
Sql:
1. select * from demo_user where name = #{name}
2. select * from demo_user where sex = #{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 映射文件

 <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.2 创建表 

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 关于返回属性的说明

  1. resultType : 只能支持字段名称属性的名称一致时才能自动映射.

  2. 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 映射文件

<?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.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.开启驼峰映射规则

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. 一对多 一个部门对应多个员工
  3. 多对多
    双向的一对多
    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对象

package com.jt.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

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对象

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 编辑测试类

package com.jt;

import com.jt.mapper.DogMapper;
import com.jt.mapper.EmpMapper;
import com.jt.mapper.UserMapper2;
import com.jt.pojo.Dog;
import com.jt.pojo.Emp;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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映射文件

<?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 一对多封装 

2.5.1 关联说明

一个部门下,对应多个员工, 主对象是Dept

 2.5.2 编辑测试类

 //完成一对多封装 一个部门中要求获取多个员工
    @Test
    public void testMore(){
        List<Dept> list = deptMapper.findAll();
        System.out.println(list);
    }

 2.5.4 编辑xml映射文件

<?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 dept.dept_name,emp.*
	    FROM dept,emp
	    WHERE emp.dept_id = dept.dept_id
    </select>
    <resultMap id="deptRM" type="Dept" autoMapping="true">
        <!--主键必须标识-->
        <id column="dept_id" property="deptId"/>
        <!-- 一对多封装 固定搭配 ofType="" -->
        <collection property="emps" ofType="Emp" autoMapping="true">
            <id column="id" property="id"></id>
        </collection>
    </resultMap>
</mapper>

 总结:

思想: 面向对象方式!!!
1.动态Sql: 不清楚用户到底传递了什么数据!!!
1.动态查询 2.动态更新 3.分支结构

关联关系
一对一/一对多/多对多(双向一对多)

resultMap 万能的数据封装的结构体系
一对一: association property=“dept” javaType=“Dept”
一对多: collection property=“emps” ofType=“Emp”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值