day10

day10

Mybatis集合操作

问题展现: 查询 id = 1 ,id = 2, id =4,id = 5,id = 6的用户信息
sql语句: select * from user where id in (1,2,4,5,6)
难点: 用户传过来的可能不是单个数值,而是数组, List集合, Map集合等

在< select >< /select > 中使用 < foreach >< /foreach > 标签

    <!--
        任务:用户传递的是数组 遍历数组
        collection: 要遍历的集合信息
            1.数组 array
            2.List集合 list
            3.Map中的key
        open="" close="" 整体标签的开始和结束
        item: 每次循环遍历的变量 类似于for循环中i变量 与后文的 #{ } 中的内容对应
        index: 遍历数据的下标
    -->
	<select id="selectIdsByMap" resultType="com.atguigu.mybatis.pojo.User">
        select * from user where id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

数组Array

接收数组用作sql语句查询
test代码
在这里插入图片描述

    private SqlSessionFactory sqlSessionFactory;
	//简化的init代码
    @Before
    public void init() throws IOException {
        String configName = "mybatis-config.xml";
        InputStream resource = Resources.getResourceAsStream(configName);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(resource);
    }
    
    @Test
    public void test01(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int[] ids = {1,2,4,5,6};
        List<User> userList = mapper.selectIds(ids);
        userList.forEach(System.out::println);
    }
    <select id="selectIds" resultType="com.atguigu.mybatis.pojo.User">
        select * from user where id in
        <foreach collection="array" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

集合List

接收List集合用作sql查询
注意:

  • int数组转化为List时,通过Arrays.asList方法转化
  • 转化时如果用 int[ ] 则转化不成功, 因为在转化List时, 需要调用get和set方法 而 int 类型中没有get和set方法. 但是在包装类中 Integer 中有get和set方法
    在这里插入图片描述
@Test
    public void test02(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Integer[] ids = {1,2,4,5,6};
        List<Integer> list = Arrays.asList(ids);
        List<User> userList = mapper.selectIdsByList(list);
        userList.forEach(System.out::println);
    }
<select id="selectIdsByList" resultType="com.atguigu.mybatis.pojo.User">
        select * from user where id in
        <foreach collection="list" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

Map

接收Map进行sql查询
在这里插入图片描述

public void test03(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Integer[] ids = {1,2,4,5,6};
        List<Integer> list = Arrays.asList(ids);
        HashMap<Object, Object> map = new HashMap<>();
        map.put("ids",list);
        List<User> userList = mapper.selectIdsByMap(map);
        userList.forEach(System.out::println);
    }

注意:

  • 遍历的是Map中的List 而不是 Map
  • foreach标签中 collection中要写对应的 key

在这里插入图片描述

<select id="selectIdsByMap" resultType="com.atguigu.mybatis.pojo.User">
        select * from user where id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

动态sql

动态查询

查询时可能单单用某个字段的属性查询,而并不是所有字段都有属性进行查询

  • 根据对象中不为null的属性,充当where条件
    想要查询某条记录
    在这里插入图片描述
@Test
    public void test04(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(null, "大乔", null, "女");
        List<User> userList = mapper.selectUser(user);
        userList.forEach(System.out::println);
    }

<if标签>动态拼接 如果id为空 sql语句报错
在这里插入图片描述
< where >可以去除 末尾多余的 1 个 and
在这里插入图片描述
< if >标签要和 < where >标签联合使用

<select id="selectUser" resultType="com.atguigu.mybatis.pojo.User">
        select * from user
            <where>
                <if test="id != null">id = #{id}</if>
                <if test="name != null and name != '' ">and name = #{name}</if>
                <if test="age != null and age != 0">and age = #{age}</if>
                <if test="sex != null and sex != '' ">and sex = #{sex}</if>
            </where>
    </select>

sql动态修改

当更新数据时, 只想修改某个字段, 则其他字段为空, 按照惯例修改, 则其他字段的null会赋值到字段中. 这时就需要判断哪些字段为空, 然后进行修改
只修改指定数据 例如 只修改 name 则 age 和 sex 为 null

在这里插入图片描述

//动态修改
    @Test
    public void test05(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(5, "华雄", null, null);
        int rows = mapper.updateUser(user);
        System.out.println("影响行数 = " + rows);
    }

在这里插入图片描述
只用< if >标签判断会造成sql语法错误 会有多余的 “,” 号
在这里插入图片描述
< set > 标签动态删除 where 后的一个 “,” 号

<!--动态更新信息-->
    <update id="updateUser">
        update user
            <set>
                <if test="name != null and name != '' ">name = #{name},</if>
                <if test="age != null and age != 0 ">age = #{age},</if>
                <if test="sex != null and sex != '' ">sex = #{sex}</if>
            </set>
        where id = #{id}
    </update>

Trim标签万能标签()

  • Trim是万能标签, 可以构建任意类型的sql语句
  • 需求: 使用trim标签实现 where 标签 的功能
  • 标签属性说明
    • prefix 在trim结构提前 添加的前缀
    • prefixOverrides: 在trim标签之前将某些标签去除
    • suffix: 在trim结构体之后添加的后缀
    • suffixOverrides: 在 trim结构体之后删除的标签

在这里插入图片描述

insert增加标签(自己写的)

<!--trim标签-->
    <insert id="insertByTrim">
        insert into user values
            <trim prefix="(" suffix=")">
                #{id},#{name},#{age},#{sex}
            </trim>
    </insert>
//Trim标签
    @Test
    public void test06(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(null, "姿儿态", 25, "男");
        int rows = mapper.insertByTrim(user);
        System.out.println("影响行数 = " + rows);
    }

分支结构

问题展现

  • 查询结果, 如果用户传入主键 id 主键,则根据主键查询
  • 如果用户没有传递主键 id 传入的是其他字段, 则需要进行判断 先判断是否传入主键 id 然后继续判断传入的自他字段
    这就是分支结构产生的原因

在这里插入图片描述
java代码

//分支结构
    @Test
    public void test07(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(null, "诸葛亮", 25, "男");
        List<User> userList = mapper.selectChoose(user);
        userList.forEach(System.out::println);
    }

xml代码

<!--分支结构-->
    <!--
        第一个when表示if
        其他when表示else-if
        otherwise表示else
    -->
    <select id="selectChoose" resultType="com.atguigu.mybatis.pojo.User">
        select * from user
            <where>
                <choose>
                    <when test="id != null">id = #{id}</when>
                    <when test="name != null">name = #{name}</when>
                    <when test="age != null">age = #{age}</when>
                    <otherwise>sex = #{sex}</otherwise>
                </choose>
            </where>
    </select>

动态sql作业

  • 批量新增
  • 准备多个对象,使用一条sql

在这里插入图片描述

在这里插入图片描述
注意: #{ } 内要写 对象.属性名 而不是直接写 属性名

结果集封装 - resultMap(重点用法)

问题展现: 查询 id ,name ,age ,sex 之后,想用 user_id, user_name, user_age, user_sex 来接收 . 但对象属性与字段不匹配. 输出结果都为null
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

    <!--
        <id>表示主键字段
            column表示对应表中的字段
            property表示对应对象中的属性
    -->
    <resultMap id="userMap" type="User">
        <!--主键字段-->
        <id column="user_id" property="id"></id>

        <!--其他字段-->
        <result column="user_name" property="name"></result>
        <result column="user_age" property="age"></result>
        <result column="user_sex" property="sex"></result>
    </resultMap>
//resultMap用法
    @Test
    public void test01(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList= mapper.selectResult();
        userList.forEach(System.out::println);
    }

补充:

<id column="user_id" property="id" javaType="Integer" jdbcType="INTEGER"></id>

可以用 javaTypejdbcType 设置强制转换

关于Mybatis中驼峰映射说明

  • 数据库中的字段与对象中的属性, 满足驼峰命名规则
    user_id -> userId
    将结果的字段按驼峰命名法直接赋值给对象 前提是对象中的属性是驼峰命名

在mybatis配置中的说明
setting name属性可以在官网找到
在这里插入图片描述
注意: setting要写在propertyis后

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

映射文件中的代码

    <select id="selectResult2" resultType="Person">
        select id user_id,name user_name,age user_age,sex user_age from user
    </select>

java代码

//驼峰命名法则
    @Test
    public void test02(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<Person> userList= mapper.selectResult2();
        userList.forEach(System.out::println);
    }

注解开发

在这里插入图片描述
@Select 写在接口方法上

public interface EmpMapper {
	//在方法上面添加注释
    @Select("select * from emp")
    List<Emp> selectList();
}

关联关系

关联关系介绍

  • 一对一
  • 一对多
  • 多对多

一对一的关联

编辑实体对象

在这里插入图片描述

基本操作
在这里插入图片描述
利用注解开发
在这里插入图片描述
查询结果缺少部门信息
在这里插入图片描述

多表关联查询

一对一

一对一

sql语句

select emp.*,dept.dept_name from emp,dept where emp.dept_id = dept.dept_id

select 
	* 
from 
	emp 
RIGHT JOIN
	dept
ON
	emp.dept_id = dept.dept_id

在这里插入图片描述
在进行数据封装时,enp 中一个属性为一个对象, 无法用正常的数据类型进行封装
在这里插入图片描述
这时就用到一个标签

< association ></ association> 标签用于属性是一个对象时

在这里插入图片描述

<select id="selectList" resultMap="empRM">
        select emp.*,dept.dept_name from emp,dept where emp.dept_id = dept.dept_id
    </select>

    <resultMap id="empRM" type="com.atguigu.mybatis.pojo.Emp">
        <id property="empId" column="emp_id"></id>
        <result property="empName" column="emp_name"></result>
        <result property="empAge" column="emp_age"></result>
        <association property="dept" javaType="Dept">
            <id property="deptId" column="dept_id"></id>
            <result property="deptName" column="dept_name"></result>
        </association>
    </resultMap>

满足驼峰命名法则 , 则可以省略
在这里插入图片描述
省略之后的输出结果
在这里插入图片描述

将< association >打开后, 将可以使用驼峰命名的语句注释掉
在这里插入图片描述
输出结果
在这里插入图片描述
关羽自动映射的说明:
1.如果没有其他关联数据(单表操作), 则满足驼峰命名规则时, 可以自动封装
2.如果是关联操作,则需手动配置 映射规则 则需要使用属性 autoMapping=“true”
3.autoMapping只对当前对象有效
打开autoMapping
在这里插入图片描述
xml代码

    <!--
        关羽自动映射的说明:
            1.如果没有其他关联数据(单表操作), 则满足驼峰命名规则时, 可以自动封装
            2.如果是关联操作,则需手动配置 映射规则 则需要使用属性 autoMapping="true"
            3.autoMapping只对当前对象有效
    -->
    <select id="selectList" resultMap="empRM">
        select emp.*,dept.dept_name from emp,dept where emp.dept_id = dept.dept_id
    </select>

    <resultMap id="empRM" type="com.atguigu.mybatis.pojo.Emp" autoMapping="true">
        <id property="empId" column="emp_id"></id>
        <!--<result property="empName" column="emp_name"></result>
        <result property="empAge" column="emp_age"></result>-->
        <association property="dept" javaType="Dept" autoMapping="true">
            <id property="deptId" column="dept_id"></id>
<!--            <result property="deptName" column="dept_name"></result>-->
        </association>
    </resultMap>

java测试代码

@Test
    public void testOneToOne(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> empList = mapper.selectList();
        /*empList.forEach(emp ->{
            System.out.println("员工信息:" + emp.getEmpName() + "~~~ 部门名称:" + emp.getDept().getDeptName());
        });*/
        empList.forEach(System.out::println);
    }

一对多

sql语句

select dept.dept_name,emp.* from emp,dept where dept.dept_id = emp.dept_id

Dept类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
    private Integer deptId;
    private String deptName;
    private List<Emp> emps;

}

在这里插入图片描述
测试代码

//一对多
    @Test
    public void testOneToMore(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> deptList = mapper.selectList();
        deptList.forEach(System.out::println);

    }

在这里插入图片描述
xml文件代码

<select id="selectList" resultMap="deptMap" >
        select dept.dept_name,emp.* from emp,dept where dept.dept_id = emp.dept_id
    </select>

    <resultMap id="deptMap" type="Dept" autoMapping="true">
        <id column="dept_name" property="deptName"></id>
        <collection property="emps" ofType="Emp" autoMapping="true">
            <id property="empId" column="emp_id"></id>
        </collection>
    </resultMap>

< collection property=“emps” ofType=“Emp” autoMapping=“true”>< id property=“empId” column=“emp_id”></ id> </ collection>

作业

  • 完成老师和学生的多对多查询

子查询介绍

使用多次查询查询, 而不是一次的联表查询

select * from dept
select * from emp where emp_id = ?

使用子查询优化sql

说明:如果数据量过大进行关联查询时性能低,所以将多表关联查询转化为多张单表查询.
运行结果中显示执行4条sql语句:
在这里插入图片描述

java测试代码

//一对多子查询方法
    @Test
    public void testOneToMoreChildQuery(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> deptList = mapper.selectListByChildQuery();
        deptList.forEach(System.out::println);
    }

xml映射文件中的配置

<!--一对多子查询-->
    <select id="selectListByChildQuery" resultMap="deptMap2">
        select * from dept
    </select>

    <resultMap id="deptMap2" type="Dept" autoMapping="true">
        <id column="dept_id" property="deptId"></id>

        <collection property="emps" ofType="Emp" select="empSelect" column="dept_id" autoMapping="true">
            <id column="emp_id" property="empId"></id>
        </collection>
    </resultMap>

    <select id="empSelect" resultType="Emp">
        select * from emp where #{dept_id}
    </select>

使用 < collection >< / collection >标签中的 select , column 标签来封装List

懒加载机制

默认是饿汉式加载
需要用到哪几个数据就查询哪几个数据, 而不是无论什么情况都进行全查找
如果全部数据都要使用则, 按照默认使用饿汉式加载
在这里插入图片描述

在< collection >< /collection >标签中添加fetchType属性来修改加载机制

可在mybatis配置文件中, 添加配置设置全局懒加载机制
在这里插入图片描述

<!--添加mybatis的设置-->
    <settings>
        <!--开启了驼峰映射规则-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--设置全局懒加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>

课堂案例

  1. 查询所有员工的信息以及所属部门的名称。
  2. 查询年龄大于等于30岁的员工信息以及所属部门的名称。
  3. 查询姓名为"张三"的员工信息以及所属部门的名称。
  4. 查询部门名称为"技术部"的员工信息。
  5. 查询年龄在25到35岁之间的员工信息以及所属部门的名称。
  6. 查询部门名称包含"销售"字样的员工信息。
  7. 查询员工数量以及每个部门的员工人数。
  8. 查询按照年龄降序排列的员工信息以及所属部门的名称。
  9. 查询姓名包含"李"字的员工信息以及所属部门的名称。
  10. 查询年龄最大的员工信息以及所属部门的名称。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值