最全面的Mybatis教程,从“开局”到“通关”(二)(中)

简介: 最全面的Mybatis教程,从“开局”到“通关”(二)(中)

十、Mybatis关联映射


以多个学生对应一个老师为例,存在:


  • 学生关联老师,多对一关系
  • 老师管理集合,一对多关系


1️⃣sql建表


  create table `teacher`(
  `id` int not null,
  `name` varchar(30) default null,
  primary key(`id`)
  ) engine=InnoDB default charset=utf8;
  insert into teacher values (1,'王老师');
  create table `student`(
  `id` int not null,
  `name` varchar(30) default null,
  `tid` int not null,
  primary key(`id`),
  key `FK_tid` (`tid`),
  constraint `FK_tid` foreign key(`tid`) references `teacher`(`id`)
  ) engine=InnoDB default charset=utf8;


2️⃣测试环境搭建


🍀(1)导入Lombok


🍀(2)新建Teacher,Student实体类


🍀(3)新建Mapper接口


🍀(4)在resources新建com->xxx->dao文件夹


🍀(5)新建xxxMapper.xml文件


🍀(6)在mybatis-config.xml中注册绑定xxxMapper.xml


🍀(7)在TeacherMapper接口中创建selectAll()方法


🍀(8)在TeacherMapper.xml中写对应的查询


🍀(9)新建测试类,在测试类中测试使用


3️⃣按照查询嵌套处理多对一


🍀实体类


Student.java:

  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  public class Student {
      private int id;
      private String name;
      private Teacher teacher;
  }

Teacher.java:

 @Data
  @AllArgsConstructor
  @NoArgsConstructor
  public class Teacher {
      private int id;
      private String name;
  }

🍀Mapper接口


List<Student> selectAll();


🍀xxxMapper.xml

  <!-- 
      查询思路:
      1.查询所有学生
      2.根据查询出的学生的tid查询老师,子查询
   -->
  <resultMap id="student_teacher" type="Student">
  <!-- property是实体类的属性 column是数据库的字段 -->
      <result property="id" column="id"/>
      <result property="name" column="name"/>
      <!--
          复杂的属性,需要单独处理,对象:association 集合collection
       -->
      <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
  </resultMap>
  <select id="selectAll" resultMap="student_teacher">
      select * from mybatis.student
  </select>
  <select id="getTeacher" resultType="Teacher">
      select * from mybatis.teacher where id=#{tid}
  </select>


🍀测试

  @Test
  public void selectAll(){
      SqlSession sqlSession = MybatisUtils.getSqlSession();
      StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      List<Student> studentList = mapper.selectAll();
      for (Student s:
           studentList) {
          System.out.println(s);
      }
      sqlSession.close();
  }

4️⃣按照结果嵌套处理多对一


🍀Mapper接口


List<Student> selectAll2();


🍀xxxMapper.xml

<select id="selectAll2" resultMap="S_T">
      select s.id sid,s.name sname,t.name tname
      from mybatis.student s,mybatis.teacher t
      where s.tid=t.id
</select>
<resultMap id="S_T" type="Student">
      <result property="id" column="sid"/>
      <result property="name" column="sname"/>
      <association property="teacher" javaType="Teacher">
          <result property="name" column="tname"/>
      </association>
</resultMap>

🍀测试

 @Test
  public void selectAll(){
      SqlSession sqlSession = MybatisUtils.getSqlSession();
      StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      List<Student> studentList = mapper.selectAll();
      for (Student s:
           studentList) {
          System.out.println(s);
      }
      sqlSession.close();
  }

5️⃣一对多关系的处理


🍀实体类

Student.java:

  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  public class Student {
      private int id;
      private String name;
      private int tid;
  }

Teacher.java:

  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  public class Teacher {
      private int id;
      private String name;
      //老师拥有多个学生
      private List<Student> students;
  }

🍀Mapper接口

public interface TeacherMapper {
      List<Teacher> selectAll();
      //获取指定老师下的所有学生
      Teacher getTeacher(@Param("tid")int id);
      Teacher getTeacher2(@Param("tid")int id);
      List<Student> getStudents(@Param("tid")int id);
  }


🍀xxxMapper.xml

   <select id="selectAll" resultType="Teacher">
      select * from mybatis.teacher
  </select>
  <select id="getTeacher" resultMap="S_T">
      select t.id tid, t.name tname,s.name sname
      from mybatis.teacher t,mybatis.student s
      where s.tid=tid and tid=#{tid}
  </select>
  <resultMap id="S_T" type="Teacher">
      <result property="id" column="tid"/>
      <result property="name" column="tname"/>
      <!-- 集合中的泛型信息,我们使用ofType -->
      <collection property="students" ofType="Student">
          <result property="name" column="sname"/>
          <result property="tid" column="tid"/>
      </collection>
  </resultMap>
  <select id="getTeacher2" resultMap="student_teacher">
      select * from mybatis.teacher where id=#{tid}
  </select>
  <resultMap id="student_teacher" type="Teacher">
      <result property="id" column="id"/>
      <result property="name" column="name"/>
      <collection property="students" column="id" ofType="Student" select="getStudents"/>
  </resultMap>
  <select id="getStudents" resultType="Student">
      select * from mybatis.student where tid=#{tid}
  </select>

🍀测试

 @Test
  public void selectAll(){
      SqlSession sqlSession = MybatisUtils.getSqlSession();
      StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      List<Student> studentList = mapper.selectAll();
      for (Student s:
           studentList) {
          System.out.println(s);
      }
      sqlSession.close();
  }

十一、Mybatis动态SQL


1️⃣动态SQL概述


MyBatis提供了对SQL语句动态的组装能力,大量的判断都可以在 MyBatis的映射XML文件里面配置,以达到许多我们需要大量代码才能实现的功能,大大减少了我们编写代码的工作量。


动态SQL的元素:


元素 作用 备注
if 判断语句 单条件分支判断
choose、when、otherwise 相当于Java中的 case when语句 多条件分支判断
trim、where、set 辅助元素 用于处理一些SQL拼装问题
foreach 循环语句 在in语句等列举条件常用


2️⃣if元素


if元素相当于Java中的if语句,它常常与test属性联合使用。现在我们要根据name去查找学生,但是name是可选的,如下所示:

<select id="findUserById" resultType="com.wang.entity.User">
    select id,username,password from user
    where 1 =1
    <if test="id != null">
        AND id = #{id}
    </if>
    <if test="username != null and username != ''">
        AND username = #{username}
    </if>
    <if test="password != null and password != ''">
        AND password = #{password}
    </if>
</select>

3️⃣where元素


上面的select语句我们加了一个1=1的绝对true的语句,目的是为了防止语句错误,变成SELECT * FROM student WHERE这样where后没有内容的错误语句。这样会有点奇怪,此时可以使用 < where> 元素。

<select id="findUserById" resultType="com.wang.entity.User">
    select id,username,password from user
    <where>
        <if test="id != null">
            AND id = #{id}
        </if>
        <if test="username != null and username != ''">
            AND username = #{username}
        </if>
        <if test="password != null and password != ''">
            AND password = #{password}
        </if>
    </where>
</select>

4️⃣trim元素


有时候我们要去掉一些特殊的SQL语法,比如常见的and、or,此时可以使用trim元素。trim元素意味着我们需要去掉一些特殊的字符串,prefix代表的是语句的前缀,而prefixOverrides代表的是你需要去掉的那种字符串,suffix表示语句的后缀,suffixOverrides代表去掉的后缀字符串。


<select id="select" resultType="com.wang.entity.User">
    SELECT * FROM user
    <trim prefix="WHERE" prefixOverrides="AND">
        <if test="username != null and username != ''">
            AND username LIKE concat('%', #{username}, '%')
        </if>
        <if test="id != null">
            AND id = #{id}
        </if>
    </trim>
</select>

5️⃣choose、when、otherwise元素


有些时候我们还需要多种条件的选择,在Java中我们可以使用switch、case、default语句,而在映射器的动态语句中可以使用choose、when、otherwise元素。

<!-- 有name的时候使用name搜索,没有的时候使用id搜索 -->
<select id="select" resultType="com.wang.entity.User">
    SELECT * FROM user
    WHERE 1=1
    <choose>
        <when test="name != null and name != ''">
            AND username LIKE concat('%', #{username}, '%')
        </when>
        <when test="id != null">
            AND id = #{id}
        </when>
    </choose>
</select>

6️⃣set元素


在update语句中,如果我们只想更新某几个字段的值,这个时候可以使用set元素配合if元素来完成。注意: set元素遇到,会自动把,去掉。


<update id="update">
    UPDATE user
    <set>
        <if test="username != null and username != ''">
            username = #{username},
        </if>
        <if test="password != null and password != ''">
            password = #{password}
        </if>
    </set>
    WHERE id = #{id}
</update>

7️⃣foreach元素


foreach元素是一个循环语句,它的作用是遍历集合,可以支持数组、List、Set接口。

<select id="select" resultType="com.wang.entity.User">
    SELECT * FROM user
    WHERE id IN
    <foreach collection="ids" open="(" close=")" separator="," item="id">
        #{id}
    </foreach>
</select>

collection配置的是传递进来的参数名称。

item配置的是循环中当前的元素。

index配置的是当前元素在集合的位置下标。

open和 close配置的是以什么符号将这些集合元素包装起来。

separator是各个元素的间隔符。


8️⃣foreach批量插入

<insert id="batchInsert" parameterType="list">
    insert into `user`( user_name, pass)
    values
    <foreach collection="users" item="user" separator=",">
        (#{user.username}, #{user.password})
    </foreach>
</insert>


9️⃣SQL片段


有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。


提取SQL片段:

<sql id="if-title-author">
   <if test="title != null">
      title = #{title}
   </if>
   <if test="author != null">
      and author = #{author}
   </if>
</sql>


引用SQL片段:

<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
       <include refid="if-title-author"></include>
       <!-- 在这里还可以引用其他的 sql 片段 -->
   </where>
</select>


相关文章
|
5月前
|
XML Java 数据库连接
MyBatis--映射关系一对一和MyBatis--映射关系多对一 -都有基于xml和注解的教程
MyBatis--映射关系一对一和MyBatis--映射关系多对一 -都有基于xml和注解的教程
90 0
|
2月前
|
XML Java 数据库连接
Mybatis-Plus学习小项目及详细教程
Mybatis-Plus学习小项目及详细教程
|
3月前
|
XML 监控 druid
【Java专题_02】springboot+mybatis+pagehelper分页插件+druid数据源详细教程
【Java专题_02】springboot+mybatis+pagehelper分页插件+druid数据源详细教程
|
3月前
|
SQL Java 数据库连接
【MyBatisPlus】通俗易懂 快速入门 详细教程
【MyBatisPlus】通俗易懂 快速入门 详细教程
79 0
|
4月前
|
Java 数据库连接 数据库
Spring Boot整合Mybatis Plus[极简教程]
Spring Boot整合Mybatis Plus[极简教程]
58 0
|
4月前
|
SQL 缓存 Java
Mybatis保姆级丝滑教程(一文搞懂系列)(2)
Mybatis保姆级丝滑教程(一文搞懂系列)
170 0
|
4月前
|
SQL Java 关系型数据库
Mybatis保姆级丝滑教程(一文搞懂系列)(1)
Mybatis保姆级丝滑教程(一文搞懂系列)
206 0
|
5月前
|
SQL JSON 数据库
MyBatis-Plus 实战教程三 拓展插件(二)
MyBatis-Plus 实战教程三 拓展插件
45 0
|
5月前
|
SQL 数据库连接 数据库
MyBatis-Plus 实战教程三 拓展插件(一)
MyBatis-Plus 实战教程三 拓展插件
53 0
|
5月前
MyBatis-Plus 实战教程四 idea插件(二)
MyBatis-Plus 实战教程四 idea插件
57 0