CGB2107-Day04-mybatis高级用法
1. Mybatis作业
1.1 模糊查询
1.1.1编辑测试类
/*
        Mybatis作业:
            需求: 查询name中包含"精"的数据.并且按照年龄降序排列
     */
    @Test
    public void findLike(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        //String name = "精";
        String name = "%精%";
        List<DemoUser> list = demoUserMapper.findLike(name);
        System.out.println(list);
        sqlSession.close();
    }
1.1.2 编辑xml映射文件
 <!--关于模糊查询的说明: 使用%号需要使用""号包裹.
        注意事项: mybatis中的sql 最好小写. 因为不同的系统对于大小写 不敏感.
        键位:  eclipse    ctrl + shift + y  小写
                         ctrl + shift + u  大写/小写
      -->
    <select id="findLike" resultType="com.jt.pojo.DemoUser">
        <!--select * from demo_user where name like "%"#{name}"%" order by age desc -->
        select * from demo_user where name like #{name} order by age desc
    </select>
1.2 批量更新操作
1.2.1 编辑测试方法
/**
     * 作业2: 将name为小乔/大乔/王昭君的年龄改为18岁,性别女
     */
    @Test
    public void updateUser(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        Map<String,Object> map = new HashMap<>();
        String[] array = {"小乔","大乔","王昭君"};
        map.put("names",array);
        map.put("age",18);
        map.put("sex","女");
        demoUserMapper.updateUser(map);
        sqlSession.close();
    }
1.2.2 编辑xml映射文件
<!--批量更新操作-->
    <update id="updateUser">
        update demo_user set age = #{age},sex = #{sex}
        where name in (
            <foreach collection="names" item="name" separator=",">
                #{name}
            </foreach>
        )
    </update>
2. Mybatis优化设置
关于Mybatis 核心配置文件的顺序
The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".
2.1 mybatis简化-别名包
2.1.1 业务说明
在mybatis xml映射文件中需要写POJO实体对象的路径. 如果每次编辑都写全路径,则开发相对繁琐. 所以mybatis引入别名包的规则.
2.1.2 实现别名配置
在mybatis的核心配置文件中 定义别名
 
2.1.3 使用别名映射

2.1.4 使用别名包
需求: 如果项目中有多个POJO实体类,如果一个一个编辑别名标签,则更为繁琐. 所以Mybatis提供了别名包的功能.
 例子:
 com.jt.pojo.User,
 com.jt.pojo.Dept,
 com.jt.pojo.Order
 原理说明: 可以设定公共的包路径 com.jt.pojo,如果设定了包路径.以后自动拼接类的全路径.
xml核心文件配置:
  <!-- 配置别名 -->
    <typeAliases>
        <!--别名标签只对某个类有效.-->
        <!--<typeAlias type="com.jt.pojo.DemoUser" alias="DemoUser"></typeAlias>-->
        <!--package 指定的是包路径的信息.-->
        <package name="com.jt.pojo"/>
    </typeAliases>
xml映射文件配置:
<mapper namespace="com.jt.mapper.DemoUserMapper">
    <!--映射原理:
        如果配置文件中定义了包路径,则映射对象时会自动的完成路径的拼接
        resultType="com.jt.pojo.DemoUser"
    -->
    <select id="findAll" resultType="DemoUser">
        select id,name,age,sex from demo_user
    </select>
</mapper>
2.1.5 别名的注解定义

2.2 Mybatis简化-Sql标签
2.2.1 业务说明
mybatis的xml映射文件中会有大量的Sql语句. 随着业务的增加,Sql语句的数量也会增加. 其中有部分**"Sql片段"则可能重复. 如果想简化Sql语句,则可以使用Sql标签**简化操作.
 例子:
 \1. select id,name,age,sex from demo_user where id = 1
 \2. select id,name,age,sex from demo_user where name = xxx
2.2.2 sql标签用法
 <!--2.简化Sql标签 -->
    <sql id="demo_user_sql">
        select id,name,age,sex from demo_user
    </sql>
    <!--include 代表包含Sql标签 -->
    <select id="findAll" resultType="DemoUser">
        <include refid="demo_user_sql"/>
    </select>
2.2.3 关于Sql标签的说明
优势:
 1.使用Sql标签可以节省xml的文件大小.
 2.代码的结构相对简单.
 弊端:
 1.Sql只能抽取公共的Sql语句,局限性稍大.
 2.如果大量的使用Sql标签,则代码的可读性差
3. Mybatis-动态Sql
3.1 IF-WHERE用法
3.1.1 业务需求
根据user对象查询数据.要求根据对象中不为null的属性充当where条件.实现动态的查询.
 案例: 实际业务中经常出现多个查询条件 如图:
 
3.1.2 编辑测试类
 /*
    *   封装DemoUser的对象,根据对象中不为null的属性查询
    * */
    @Test
    public void testFindWhere(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        DemoUser demoUser = new DemoUser();
        demoUser.setAge(3000);
        List<DemoUser> list = demoUserMapper.findWhere(demoUser);
        System.out.println(list);
        sqlSession.close();
    }
3.1.3 编辑xml映射文件
  <!--动态Sql案例
        思路: 如果数据不为null,mybatis才会当做条件
        if标签说明:
            test: 判断的条件 直接写属性即可
        where标签: 去除条件中多余的 and 或者 or的
        说明: if和 where 几乎一起出现.
    -->
    <select id="findWhere" resultType="DemoUser">
        select id,name,age,sex from demo_user
            <where>
                <if test="name != null">name = #{name}</if>
                <if test="age !=null"> and age=#{age}</if>
                <if test="sex !=null"> and sex=#{sex}</if>
            </where>
    </select>
3.2 动态Sql-SET标签
3.2.1 编辑测试案例
 /**
     * 需求: 根据Id,动态的实现数据的更新.
     */
    @Test
    public void testUpdateSet(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        DemoUser user = new DemoUser();
        user.setId(1).setName("守山大使");
        demoUserMapper.updateUser(user);
        sqlSession.close();
    }
3.2.2 编辑mapper接口

3.2.3 编辑xml映射文件
 <!--
        规则: 根据对象中不为null的属性当做set条件
        set标签说明: 去除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>
3.3 动态Sql-choose when otherwise
3.3.1 业务需求
根据条件实现数据的查询. 如果存在name则按照name查询,否则按照sex查询.
 补充说明:
 条件: name = “张三” , sex=“男”
 select * from demo_user where name = #{name}
3.3.2 编辑测试类
 /**
     * 需求: 如果存在name则按照name查询,否则按照sex查询.
     */
    @Test
    public void testSelectChoose(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        DemoUser user = new DemoUser();
        user.setSex("男");
        List<DemoUser> list = demoUserMapper.selectChoose(user);
        System.out.println(list);
        sqlSession.close();
    }
3.3.3 编辑xml映射文件
 <!--
        需求: 如果不想将全部的条件当做if的判断.则mybatis提供了分支结构 switch
        语法说明:
              choose:代表分支结构,只有一个条件有效.
              when: 指定判断的条件 和if类似.
              otherwise: 如果上述的条件都不满足时,该行代码有效.
    -->
    <select id="selectChoose" resultType="DemoUser">
        select * from demo_user
        where
            <choose>
                <when test="name !=null">name = #{name}</when>
                <otherwise>sex = #{sex}</otherwise>
            </choose>
    </select>
4 ResultMap
4.1 项目构建
4.1.1 创建表
- 创建dept表 int dept_id 主键自增, varchar类型(40) dept_name
  
4.1.2 编辑Dept POJO对象
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable{
    //驼峰命名规则
    private Integer deptId;
    private String deptName;
}
4.2 resultType与resultMap用法
4.2.1 标签说明
resultType说明:
 当结果集中的字段名称,如果与属性的名称一致时,才会实现自动的数据封装
 resultMap说明:
 当结果集中的字段名称,与对象中的属性不一致时,可以使用resultMap实现自定义的封装.
4.2.2 编辑测试类
@Test
    public void testFindDept(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.findAll();
        System.out.println(list);
        sqlSession.close();
    }
12345678
4.2.3 编辑业务接口

4.2.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">
    <!--
        ORM思想: 对象关系映射.
        属性: deptId,deptName
        字段: dept_id,dept_name
        resultType说明:
             当结果集中的字段名称,如果与属性的名称一致时,
             才会实现自动的数据封装.
        resultMap="" 自定义的封装数据的结构
    -->
    <select id="findAll" resultMap="deptRM">
        select * from dept
    </select>
    <!--自定义映射关系的
        语法:
            1.id标签代表主键 (每张表中都会有一个主键)
                1.1.column: 代表结果集中的字段.
                1.2.property: 对象中的属性
            2.result 除了主键之外的配置信息
    -->
    <resultMap id="deptRM" type="Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
    </resultMap>
</mapper>
5. 关联关系
5.1 常见关联关系
- 一对一 例子: 1.人和身份证号 2. 老公和老婆 3. 员工和部门
- 一对多 例子: 一个部门对应多个员工.
- 多对多 老师和学生
 一个老师对应多个学生.
 一个学生对应多个老师.
 核心: 考虑问题从一头出发.
5.2 一对一
5.2.1 创建表
表名: emp 员工表
 字段: id,name,age,dept_id
 
表数据说明:
 
5.2.2 构建代码结构
5.2.2.1 创建POJO
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Emp implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private Integer deptId;
}
5.2.2.2 创建EmpMapper接口

5.2.2.3 创建EmpMapper.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">
</mapper>

5.2.2.4 mybatis加载xml映射文件
说明: 编辑mybatis-config.xml文件,添加映射文件.
 
5.2.3 一对一业务封装
规则: 如果对一 则使用对象封装.
 如果对多 则使用List集合封装
总结
-  作业: 模糊查询的用法 “%”#{xxxx}"%", setName("%xxxx%") 
-  如果遇到多值传参, 一般封装为Map集合. 1
-  mybatis-config.xml 文件的配置是有顺序的. 不能随意 
-  别名写法 1.别名标签 2. 别名包 3. 注解 
-  Sql标签 将公共的sql进行抽取 通过sql标签进行定义. 
-  动态Sql where-if / set / choose when 
-  resultMap用法: 解决字段与属性名称不一致的问题. 
-  resultType: 单表查询时/属性与字段一样时, 
-  关联关系的用法 一对一 一对多 










