动态SQL和多表关联-笔记

这篇博客详细记录了MyBatis中动态SQL的使用,包括if、where、set和foreach标签的应用,以及如何通过resultMap实现多表查询。此外,还介绍了如何配置映射文件和创建会话工具类。博主通过实际案例展示了动态SQL在更新和插入操作中的应用,以及一对一和一对多关联查询的实现方法。最后,对所学内容进行了总结。
摘要由CSDN通过智能技术生成

《动态SQL与多表关联》笔记

学习目标

  1. 能够使用动态SQL完成SQL拼接
  2. 能够使用resultMap完成多表查询
  3. 能够使用一对一查询
  4. 能够使用一对多查询 (注:多对多其实就是两个一个多)

映射文件:为什么要resultMap

目标

  1. 定义结果映射

  2. 使用结果映射

回顾

在mybatis中有2种配置文件:

  1. 核心配置文件,如:sqlMapConfig.xml
  2. 实体类映射文件,如:UserMapper.xml

实体类映射文件2个功能:

  1. 编写SQL语句
  2. 指定实体类与表之间映射关系

第2个功能还没用到,如果一张表中所有的列名与实体类中属性名全部相同,就不需要映射。

在这里插入图片描述

如果表中列名与实体类中属性名有不同,必须要映射,否则这列的数据就无法封装。

步骤

修改表结构

-- 复制user为user2新表,新复制的表没有主键约束,没有自增
create table user2 select * from user;

-- 添加主键约束
alter table user2 add primary key (id);

-- 增加自增功能
alter table user2 modify id int auto_increment;

-- 从100开始自增
alter table user2 auto_increment = 100;

-- 修改用户表结构,将用户名字段由username改成user_name
alter table user2 change username user_name varchar(20);

select * from user2;

查询结果如下

在这里插入图片描述

复制idea原来项目

  1. 在windows下复制原来的项目整个目录,并且改名。
    在这里插入图片描述

  2. 修改项目中的文件名,项目的描述文件
    在这里插入图片描述

  3. 在idea中导入项目

在这里插入图片描述

  1. 选择上面修改过的文件

在这里插入图片描述

  1. 如果使用idea插件,每次只能开一个mybatis项目,不然有时会发现DAO接口和XML映射文件有报错

  2. 删除UserMapper接口中所有的方法,删除UserMapper.xml中所有的配置,删除测试中所有测试的方法

数据库名字要修改

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/day26
jdbc.username=root
jdbc.password=root

用户实体类不变

package com.itheima.entity;

import java.sql.Date;

/**
 用户实体类对象 */
public class User {
   

    private Integer id;   //注:使用大写
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public User() {
   
    }

    public User(Integer id, String username, Date birthday, String sex, String address) {
   
        this.id = id;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

	 //get和set省略
    @Override
    public String toString() {
   
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

UserMapper接口

User findUser2ById(Integer id);

映射文件

<?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.itheima.dao.UserMapper">

    <!--查询user2的表-->
    <select id="findUser2ById" resultType="user">
        select id,user_name as username,birthday,sex,address from user2 where id=#{id}
    </select>
</mapper>

结果如下

配置前:

在这里插入图片描述

解决方法:

  1. 使用别名,给user_name定义别名,别名名字与username相同

    select id,user_name as username,birthday,sex,address from user2 where id=#{id}
    
  2. resultMap来实现实体类与表中列映射

映射文件:resultMap输出类型

使用resultMap实现

说明:resultMap用于配置sql语句中字段(列)的名称,与java对象中属性名称的对应关系。本质上还是要把执行结果映射到java对象上。分两步:

  1. 使用resultMap来定义一个映射关系,并且给这个映射id的属性,这个id在同一个配置文件中要唯一

  2. 在查询的时候,将查询的结果设置为上面的映射,通过id来引用

配置mapper映射文件

  1. 定义映射,指定id和type,type为实体类的别名
  2. id标签:映射主键字段,如果列名与属性名相同可以省略
  3. result标签:映射普通字段,指定哪个属性对应哪个列,这里只需映射username即可
  4. 在查询的结果中使用resultMap,为上面的映射id
<?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.itheima.dao.UserMapper">

    <!--
    1. 使用resultMap来定义一个映射关系
    id:给这个映射唯一标识
    type:对应的实体类的类型
    -->
    <resultMap id="userMap2" type="user">
        <!--
        id子元素:用于指定主键映射(如果列名与属性名相同,可以不映射)
        属性:
            column 指定表中列名
            property 指定实体体中属性名
            javaType 指定属性名的数据类型
        result:子元素用于定义其它列的映射,两个属性与上面含义相同,只映射不同的列
        -->
        <id column="id" property="id"/>
        <result column="user_name" property="username"/>
    </resultMap>

    <!--
    2. 查询user2的表的时候,通过id引用上面的映射关系
    resultType 直接指定实体类的别名
    resultMap 指定定义的映射关系
     -->
    <select id="findUser2ById" resultMap="userMap2">
        select id,user_name,birthday,sex,address from user2 where id=#{id}
    </select>
</mapper>

测试

查询id为1的用户

@Test
public void testFindUser2ById() {
   
    User user = userMapper.findUser2ById(1);
    System.out.println(user);
}

执行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m8GVqcaQ-1592726289127)(assets/image-20200516094550680.png)]

映射流程

在这里插入图片描述

映射文件的标签小结

标签 子标签 说明
<resultMap> 定义表的字段名与实体类的属性名之间映射关系
<id> 定义主键列
<result> 定义其它列

创建会话的工具类

目标

创建会话的工具类

需求

因为以后每天都需要使用会话对象,如果每次都完整的写一次,比较麻烦。创建一个工具类,调用一个方法获取会话对象。

步骤

  1. 在静态代码块中创建会话工厂
  2. 编写静态方法得到会话

代码

package com.itheima.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * 创建会话的工具类
 */
public class SqlSessionUtils {
   

    private static SqlSessionFactory factory;

    /**
     * 在静态代码块中创建会话工厂
     */
    static {
   
        //0.创建核心配置文件的输入流
        try (InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml")) {
   
            //1.创建工厂建造类
            SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
            //2.创建会话工厂,读取核心配置文件
            factory = factoryBuilder.build(inputStream);
        } catch (IOException e) {
   
            e.printStackTrace();
        }
    }

    /**
     * 编写一个静态方法获取会话
     */
    public static SqlSession getSession() {
   
        return factory.openSession();
    }

}

动态SQL:环境搭建

目标

  1. 学习哪些动态SQL标签
  2. 复制项目

MyBatis动态SQL

以前:我们的SQL语句都是直接写死在配置文件中,一但写好了就固定了。

概念:在代码的执行过程中,根据代码的执行情况动态拼接成不同的SQL语句

将要学习的标签:类似于JSTL中标签

  1. if 在XML中进行判断,如果符合条件就进行拼接
  2. where 类似于sql where语句
  3. set 用于更新的操作
  4. foreach 对集合或数组进行遍历
  5. sql 定义一个SQL代码片段
  6. include 引用上面代码片段

需求

  1. 根据用户名称和性别查询用户数据
  2. 姓名是模糊查询
  3. 查询User表

声明UserMapper接口方法

  1. 根据用户名称和性别查询用户
  2. 参数是User对象
/**
 * 根据用户名称和性别查询用户
 */
List<User> findUserByNameAndSex(User user);

配置mappr映射文件

<!--根据用户名称和性别查询用户-->
<select id="findUserByNameAndSex" resultType="user">
    select * from user where username like "%"#{username}"%" and sex = #{sex}
</select>

执行效果

在这里插入图片描述

测试

@Test测试方法中通过用户名和性别查询多个用户,查询条件是"精"和"女"

@Test
public void testFindUserByNameAndSex() {
   
    //封装查询条件
    User user = new User();
    user.setUsername("精");
    user.setSex("女");
    List<User> users = userMapper.findUserByNameAndSex(user);
    System.out.println(users);
}

动态SQL:if和where标签

目标

  1. 动态SQL语句if标签的使用
  2. 动态SQL语句where标签的使用

应用场景

如果使用一个实体类来封装所有的查询条件,如果这个实体类属性有值,则参与查询,否则就不做为查询条件。

在这里插入图片描述

if标签

作用

判断某个条件是否为真,如果为真则拼接标签体中的SQL语句

UserMapper.xml

  1. 根据用户名称和性别查询用户
  2. if:判断用户名称不为空,且不为空字符串,则作为查询条件
  3. if:判断用户性别不为空,且不为空字符串,则作为查询条件
<!--
根据用户名称和性别查询用户
if 标签的作用:判断某个条件是否为真,如果为真则拼接标签体中的SQL语句
-->
<select id="findUserByNameAndSex" resultType="user">
    select * from user where
    <if test="username!=null and username!=''">
        username like "%"#{username}"%"
    </if>
    <if test="sex!=null and sex!=''">
        and sex = #{sex}
    </i
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值