文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MyBatis复杂Sql查询如何实现

2023-07-04 21:02

关注

这篇文章主要介绍“MyBatis复杂Sql查询如何实现”,在日常操作中,相信很多人在MyBatis复杂Sql查询如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MyBatis复杂Sql查询如何实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

resultMap 结果映射

resultMap 元素是 MyBatis 中最重要最强大的元素,之前所写的 sql 语句,返回值都是简单的基本数据类型或者某一个实体类,比如下面这段 sql 返回的就是最简单的 User 类型。

<select id="getUserById" resultType="user" parameterType="int">    select * from user where id=#{id};</select>

现在思考一下下面这种情况,如果实体类中定义的某一个字段和数据库中的字段不一致怎么办?

public class User {    private int id;    private String lastname;    //.....}

比如我定义了一个 User 类,包含 id 和 lastname 两个属性,而数据库中这两个字段的名字为 id 和 name。此时再执行查询时结果如下:lastname 这个字段直接为 null。

这时候我们就可以使用 resultMap 来解决这个问题,resultMap 可以将数据库中的字段映射到实体类上。column 代表数据库中的字段名,properties 代表实体类中的字段名,通过映射之后 Mybatis 就可以找到对应的字段。

<resultMap id="UserMap" type="User">    <!--column代表数据库中的字段名,properties代表实体类中的字段名-->    <result column="id" property="id"/>    <result column="name" property="lastname"/></resultMap><select id="getUserById" resultMap="UserMap" parameterType="int">  select * from user where id=#{id};</select>

准备数据

接下来结合学生与教室的案例模拟复杂场景:

//创建教室表create table classroom(id int not null AUTO_INCREMENT,classname VARCHAR(40) not null,PRIMARY KEY (id));//创建学生表create table student(id int not null AUTO_INCREMENT,name VARCHAR(40) not null,classid int not null,PRIMARY KEY (id),FOREIGN key (classid) REFERENCES classroom(id));//创建一些数据insert into classroom VALUES (1,'101班');insert into classroom VALUES (2,'102班');insert into student VALUES(1,'Amy',1);insert into student VALUES(2,'Bob',1);insert into student VALUES(3,'javayz',1);

多对一查询(association)

现在要实现一个多对一的查询需求,查询所有的学生,并将每个学生所在的教室包含在内。由于现在的情况是多学生和教室的关系是多对一,因此在构建实体类时在 Student 类上要加上 ClassRoom 变量。

在 Java 的实体类代码中分别建立 Student 和 ClassRoom 的类:

package com.cn.pojo;public class ClassRoom {    private int id;    private String classname;    public ClassRoom(){}    public int getId() {        return id;    }    public String getClassname() {        return classname;    }    public void setId(int id) {        this.id = id;    }    public void setClassname(String classname) {        this.classname = classname;    }    @Override    public String toString() {        return "ClassRoom{" +                "id=" + id +                ", classname='" + classname + '\'' +                '}';    }}
package com.cn.pojo;public class Student {    private int id;    private String name;    private ClassRoom classRoom;    public Student(){}    public int getId() {        return id;    }    public String getName() {        return name;    }    public ClassRoom getClassRoom() {        return classRoom;    }    public void setId(int id) {        this.id = id;    }    public void setName(String name) {        this.name = name;    }    public void setClassRoom(ClassRoom classRoom) {        this.classRoom = classRoom;    }    @Override    public String toString() {        return "Student{" +                "id=" + id +                ", name='" + name + '\'' +                ", classRoom=" + classRoom +                '}';    }}

定义一个 StudentMapper 接口:

package com.cn.mapper;import java.util.List;import com.cn.pojo.Student;public interface StudentMapper {    List<Student> selectAllStudent();}

编写 StudentMapper.xml

<?xml version="1.0" encoding="UTF8" ?><!DOCTYPE mapper        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.cn.mapper.StudentMapper">    <select id="selectAllStudent" resultMap="StudentAndClassRoom">        select s.id sid,s.name sname,c.id cid,c.classname cname        from student s,classroom c        where s.classid=c.id    </select>    <resultMap id="StudentAndClassRoom" type="com.cn.pojo.Student">        <result property="id" column="sid"/>        <result property="name" column="sname"/>        <association property="classRoom" javaType="com.cn.pojo.ClassRoom">            <result property="id" column="cid"/>            <result property="classname" column="cname"/>        </association>    </resultMap></mapper>

上面的这种 sql 编写模式称为结果嵌套查询,首先通过一段 sql 查询语句将需要的信息查询出来,接着通过 resultMap 对结果进行拼接。这里使用 association 将 classRoom 的信息拼接到了 classRoom 类中,实现多对一查询。

别忘了在配置类里把 mapper 映射加上,编写测试类:

public class StudentMapperTest {    public static void main(String[] args) {        // 获取SqlSession        SqlSession sqlSession = MyBatisUtils.getSqlSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        List<Student> students = mapper.selectAllStudent();        System.out.println(students);    }}

一对多查询(collection)

一个教室里有多个学生,如果想要查询每个教室中的所有学生,就会用到一对多查询。

修改两个实体类,命名为 Student2 和 ClassRoom2,因为一个教室中有多个学生,因此在教室类中通过 List<Student2> 的方式引入 Student2 类

public class Student2 {    private int id;    private String name;    private int classId;    @Override    public String toString() {        return "Student{" +                "id=" + id +                ", name='" + name + '\'' +                ", classId=" + classId +                '}';    }}
import java.util.List;public class ClassRoom2 {    private int id;    private String classname;    private List<Student2> students;    @Override    public String toString() {        return "ClassRoom{" +                "id=" + id +                ", classname='" + classname + '\'' +                ", students=" + students +                '}';    }}

接着编写 Mapper 接口和对应的 Mapper.xml

import java.util.List;import com.cn.pojo.ClassRoom2;public interface ClassRoomMapper {    List<ClassRoom2> getClassRoomByid( int id);}
<?xml version="1.0" encoding="UTF8" ?><!DOCTYPE mapper        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.cn.mapper.ClassRoomMapper">    <select id="getClassRoomByid" resultMap="ClassRoomAndStudent" parameterType="int">        select c.id cid,c.classname cname,s.id sid,s.name sname,s.classid classid        from student s,classroom c        where s.classid=c.id and c.id=#{id}    </select>    <resultMap id="ClassRoomAndStudent" type="com.cn.pojo.ClassRoom2">        <result property="id" column="cid"/>        <result property="classname" column="cname"/>        <!--对于集合属性,需要使用collection来实现-->        <collection property="students" ofType="com.cn.pojo.Student2">            <result property="id" column="sid"/>            <result property="name" column="sname"/>            <result property="classId" column="classid"/>        </collection>    </resultMap></mapper>

依旧是通过结果嵌套查询的方式,通过 sql 语句查询出结果,再通过 resultMap 进行组装,一对多查询用的是 collection。

在配置文件中增加 mapper 映射器之后,编写一个测试类:

public class TeacherMapperTest {    public static void main(String[] args) {        // 获取SqlSession        SqlSession sqlSession = MyBatisUtils.getSqlSession();        ClassRoomMapper mapper = sqlSession.getMapper(ClassRoomMapper.class);        List<ClassRoom2> classRoom = mapper.getClassRoomByid(1);        System.out.println(classRoom);    }}

总结成一点:对象的关联(多对一)使用 association,集合的关联(一对多)使用 collection。

懒加载

在上面的两个例子中,一次 sql 查询就将两个表的数据一次性查询了出来,这种方式就是即时加载。但是在某些业务场景下,可能只需要学生的信息或者教室的信息,而不需要两者的联表数据,这种时候就可以使用懒加载。

以上边的 association 案例解释懒加载的实现。

上边的例子中,通过联表查询一次性就查询出了学生信息和教室信息:

select s.id sid,s.name sname,c.id cid,c.classname cnamefrom student s,classroom cwhere s.classid=c.id

如果想要通过懒加载实现,就需要把 sql 语句转换为:

select * from student;select * from classroom where id = #{classid}

按照这个思路,建立 StudentLazyMapper 类:

package com.cn.mapper;import java.util.List;import com.cn.pojo.Student;public interface StudentLazyMapper {    List<Student> selectAllStudent();}

创建对应的 StudentLazyMapper.xml 文件,将原先的一条 sql 转换为两条 sql:

<?xml version="1.0" encoding="UTF8" ?><!DOCTYPE mapper        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.cn.mapper.StudentLazyMapper">    <select id="selectAllStudent" resultMap="studentAndClassRoom">        select * from student    </select>    <resultMap id="studentAndClassRoom" type="com.cn.pojo.Student">        <id property="id" column="id"/>        <result property="name" column="name"/>        <association property="classRoom" javaType="com.cn.pojo.ClassRoom" column="classid" select="selectClassRoomById">            <result property="id" column="id"/>            <result property="classname" column="classname"/>        </association>    </resultMap>    <select id="selectClassRoomById" resultType="com.cn.pojo.ClassRoom">        select * from classroom where id = #{classid}    </select></mapper>

在 mybatis-config.xml 中增加 mapper 映射,为了更好地看到懒加载效果,开启控制台日志输出,完整 xml 如下:

<?xml version="1.0" encoding="UTF8" ?><!DOCTYPE configuration        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><settings>    <setting name="logImpl" value="STDOUT_LOGGING"/></settings>    <environments default="development">        <environment id="development">            <transactionManager type="JDBC"/>            <dataSource type="POOLED">                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>                <property name="username" value="root"/>                <property name="password" value=""/>            </dataSource>        </environment>    </environments>    <!--每个mapper.xml都需要在mybatis配置文件中进行配置-->    <mappers>        <mapper resource="mapper/UserMapper.xml"/>        <mapper resource="mapper/StudentMapper.xml"/>        <mapper resource="mapper/StudentLazyMapper.xml"/>    </mappers></configuration>

新建一个测试类 StudentMapperLazyTest:

public class StudentMapperLazyTest {    public static void main(String[] args) {        // 获取SqlSession    SqlSession sqlSession = MyBatisUtils.getSqlSession();    StudentLazyMapper mapper = sqlSession.getMapper(StudentLazyMapper.class);    List<Student> students = mapper.selectAllStudent();    System.out.println(students.get(0).getId());    }}

这个时候是还没开启懒加载的,从运行结果可以看出,虽然代码中只需要得到 student 的 id,但是却查询了两张表:

MyBatis复杂Sql查询如何实现

在配置文件的 setting 节点下开启懒加载的配置:

<setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/>

再次运行测试代码:

MyBatis复杂Sql查询如何实现

可以看到,只有 student 一张表被查询,实现了懒加载

到此,关于“MyBatis复杂Sql查询如何实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯