MyBatis详解——多表关联及动态SQL

MyBatis详解——多表关联及动态SQL

今天继续学习Mybatis相关的知识,这次来说说多表关联及动态SQL。

多表关联

何为多表关联,顾名思义,也就是两张以上表相互关联操作。

今天主要讲下一对一和一对多的多表关联。

一对一

何为一对一?就像一本图书对应一种图书类型。

下面我就用图书表book和图书类型表booktype演示下一对一的实现。

实例步骤

1.先创建实体类Book类和BookType类

package com.lanou3g.mybatis.bean;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class Book {
    private Integer id;
    private String bname;
    private BookType bookType;
    private String author;
    private String authorGender;
    private Float price;
    private String description;


    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", bname='" + bname + '\'' +
                ", bookType=" + bookType +
                ", author='" + author + '\'' +
                ", authorGender='" + authorGender + '\'' +
                ", price=" + price +
                ", description='" + description + '\'' +
                '}';
    }
}
package com.lanou3g.mybatis.bean;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class BookType {
    private Integer id;
    private String tname;

    @Override
    public String toString() {
        return "BookType{" +
                "id=" + id +
                ", tname='" + tname + '\'' +
                '}';
    }
}

2.配置 mybatis_conf.xml文件(它主要引入外部的properties文件(用于配置数据源)、定义类型别名(全局)、配置多套环境的数据库连接参数及引入哪些Mapper映射文件等)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 引入外部的properties文件,只能引入一个 -->
    <properties resource="jdbc.properties" />
    
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="false"/>
    </settings>
    
    <!-- 定义类型别名(全局),在所有的Mapper.xml中都可以用 -->
    <typeAliases>
        <typeAlias type="com.lanou3g.mybatis.bean.Teacher" alias="Teacher" />
        <typeAlias type="com.lanou3g.mybatis.bean.Student" alias="Student" />
    </typeAliases>
    <!-- 配置多套环境的数据库连接参数(如:开发环境、生产环境) -->
    <environments default="lanou">
    <environment id="lanou">
        <!-- 事务管理器:
            MANAGED: 这个配置就是告诉mybatis不要干预事务,具体行为依赖于容器本身的事务处理逻辑。
            JDBC: 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
         -->
        <transactionManager type="MANAGED"/>
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
</environments>
    <mappers>
       <mapper class="com.lanou3g.mybatis.dao.StudentDao/>
        <mapper resource="mapper/TeacherMapper.xml" />
        <mapper resource="mapper/StudentMapper.xml" />
        <mapper resource="mapper/BookMapper.xml"/>
    </mappers>
</configuration>

3.配置映射文件 BookMapper.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.lanou3g.mybatis.dao.BookDao">
    <resultMap id="book" type="com.lanou3g.mybatis.bean.Book">
    <id column="bid" property="id" />
        <result column="bname" property="bname" />
        <result column="author" property="author" />
        <result column="author_gender" property="authorGender" />
        <result column="price" property="price" />
        <result column="description" property="description" />
    <association property="bookType" javaType="com.lanou3g.mybatis.bean.BookType">
            <id column="t_id" property="id"/>
            <result column="tname" property="tname"/>
    </association>
    </resultMap>
    <select id="queryBooks" resultMap="book">
                select b.*,t.*, b.id bid, t.id t_id from book b, booktype t where b.btype = t.id;
    </select>
</mapper>

4.定义接口类 BookDao.java,在其中定义与映射文件中select标签相对应得方法

package com.lanou3g.mybatis.dao;
import com.lanou3g.mybatis.bean.Book;
import java.util.List;
public interface BookDao {
    List<Book> queryBooks();
}

5.最后在测试类测试方法

 /**
     * 一对一关联查询
     */
    @Test
    public void testQueryCascade() {
        List<Book> bookList = bookDao.queryBooks();
        log.info("关联查询图书表:" + bookList);
    }

一对多

何为一对多?一个老师拥有多个学生,一个学生属于某个老师。

下面我就用教师表teacher和学生表student演示下一对多的实现。

实例步骤

1.先创建实体类Teacher和Student

package com.lanou3g.mybatis.bean;

import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
public class Teacher {
    private Integer id;
    private String tname;
    private Integer age;
    private Integer salary;
    private String remark;
    private List<Student> students;

    public Teacher (){}

    public Teacher(String tname) {
        this.tname = tname;
    }

    public Teacher(Integer id, String tname, Integer age, Integer salary, String remark) {
        this.id = id;
        this.tname = tname;
        this.age = age;
        this.salary = salary;
        this.remark = remark;

    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", tname='" + tname + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                ", remark='" + remark + '\'' +
                ", students=" + students +
                '}';
    }
}
package com.lanou3g.mybatis.bean;


import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Student {
    private Integer id;
    private String name;
    private Integer gender;
    private Integer age;



    public Student() {}


    public Student(Integer id, String name, Integer gender, Integer age) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.age = age;

    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender=" + gender +
                ", age=" + age  +
                '}';
    }

    public Student(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
}

2.配置 mybatis_conf.xml文件,上面一对一已有说明。

3.配置映射文件 TeacherMapper.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">


<!-- namespace对应空Dao接口的全名 -->
<mapper namespace="com.lanou3g.mybatis.dao.TeacherDao">
    <resultMap id="teacher" type="Teacher" >
        <id column="t_id" property="id" />
        <result column="tname" property="tname" />
        <result column="age" property="age" />
        <result column="salary" property="salary" />
        <result column="remark" property="remark" />
        <collection property="students" ofType="Student">
            <id column="s_id" property="id" />
            <result property="id" column="sid" />
            <result property="name" column="name" />
            <result property="age" column="age" />
            <result property="gender" column="gender"/>
        </collection>

    </resultMap>

    <select id="queryTeacherCascade" resultMap="teacher">
        SELECT t.*,s.*,t.id t_id,s.id s_id from teacher t, student s WHERE t.id = s.tid;
    </select>

 
</mapper>

4.定义接口类TeacherDao.java,在其中定义与映射文件中select标签相对应得方法

package com.lanou3g.mybatis.dao;

import com.lanou3g.mybatis.bean.Teacher;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface TeacherDao {

    List<Teacher> queryAll();
    List<Teacher> queryTeacherCascade();
}

5.测试

  /**
     * 一对多关联查询
     */
    @Test
    public void testQueryTeacherCascade() {
        List<Teacher> teacherList = teacherDao.queryTeacherCascade();
        log.info("关联查询教师表:" + teacherList);
    }

动态SQL

1.简介

首先什么是动态SQL? 动态SQL有什么作用?

传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误。Mybatis的动态SQL功能正是为了解决这种问题, 其通过 if, choose, when, otherwise, trim, where, set, foreach标签,可组合成非常灵活的SQL语句,从而提高开发人员的效率。下面就去感受Mybatis动态SQL的魅力吧。

用官方的话说:

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

要学习的mybatis动态 SQL 元素如下:

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

2.where和if

mybatis中使用 where和if 组合

代码示例:

先在映射文件中配置

select id="queryStudentByCondition" resultType="Student">
        select * from student
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="name!=null">
                and name=#{name}
            </if>
        </where>
    </select>

再定义接口类方法

  List<Student> queryStudentByCondition(Student condition);

测试

  @Test
    public void testQueryDynamicSQL(){
        Student stu=new Student();
        stu.setId(6);
        stu.setName("后土");
        List<Student> studentList=studentDao.queryStudentByCondition(stu);
        log.info("where..if...学生列表:" + studentList);
    }

3.choose和if

mybatis中使用 choose和if 组合

代码示例:

先在映射文件中配置

<select id="queryStudentByChooseWhen" resultType="Student">
        select * from student
        <where>
            <choose>
                <when test="name != null">
                    and name = #{name}
                </when>
                <when test="id != null">
                    and id = #{id}
                </when>
                <otherwise>
                    and id = 5
                </otherwise>
            </choose>
        </where>
    </select>

再定义接口类方法

 List<Student> queryStudentByChooseWhen(Student condittion);

测试

  @Test
    public void testQueryDynamicSQL(){
        Student stu=new Student();
        stu.setId(4);
        stu.setName("共工");
        studentList = studentDao.queryStudentByChooseWhen(stu);
        log.info("choose..when...学生列表:" + studentList);
    }

4.set和trim

<update id="updateStu" parameterType="Student">
        update student
        <!--<set>
            <if test="id!=null">
                id=#{id},
            </if>
            <if test="name!=null">
                 name=#{name}
            </if>
        </set>-->
        <trim prefix="set" suffixOverrides=",">
            <if test="id!=null">
                id=#{id},
            </if>
            <if test="name!=null">
                name=#{name},
            </if>
        </trim>
        where id = #{id}
    </update>

定义接口类方法

 int updateStu(Student condition);

测试

  @Test
    public  void testUpdateDynamicSQL(){
        Student student=new Student();
        student.setId(5);
        student.setName("玄冥");
        int rows = studentDao.updateStu(student);
        log.info("更新行数: " + rows);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lic_dream

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值