MyBatis的关联查询实现,基于XML配置的实现,重点练习MyBatis的一对一,一对多的查询, mapper.xml文件配置, SqlSession的操作。

前言

完成课上的实验作业,想再熟悉一下以配置文件的方式来使用MyBatis,以往都是使用SpringBoot + MyBatis的开发方式。

这篇文章讲的是基于配置文件来使用MyBatis操作数据库,包括MyBatis的一对一、一对多的查询,并将结果封装成Java中的DTO,注意,这里也可以不用使用DTO,像”将A实体作为B实体的属性“,这样的操作也是可以的,看个人习惯啦。

在本篇文章中,我会在使用以上的两种方式来实现本案例,重点放在DTO模式上。

案例要求

场景描述:有一个数据库mybatis,里面有一张表student,包含5个字段:id,name,sex,classno,age(学号,姓名,性别,班号,年龄),一张班级表class(cno, cname, number, teacher).学生对班级是一对一的关系, 班级对学生是一对多的关系,实现一对一的关联查询,一对多的关联查询。 实现以上的相关查询,并测试。

案例环境:IDEA + MySQL + MyBatis
知识点:使用association实现一对一查询功能,association、collection混合使用实现一对多查询功能

实现

  • 创建一个原生的maven项目

    在这里插入图片描述
  • 添加相关的依赖

<!--mybatis-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>

<!--mysql-connector-java-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

<!--指定vfs,避免控制台输出mybatis的日志乱码-->
<dependency>
    <groupId>org.jboss</groupId>
    <artifactId>jboss-vfs</artifactId>
    <version>3.2.15.Final</version>
</dependency>

<!--测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
    <scope>test</scope>
</dependency>
  • 案例的架构

按照架构创建相应的包和文件夹即可

在这里插入图片描述

  • 实体类

package com.openallzzz.entity;

import java.util.List;

public class Class { // 班级类

    private String cno;
    private String cname;
    private int number;
    private String teacher;
    // 这里多的一个属性就是用来演示不用 DTO 如何完成本案例
    private List<Student> studentList;

    @Override
    public String toString() {
        return "Class{" +
                "cno='" + cno + '\'' +
                ", cname='" + cname + '\'' +
                ", number=" + number +
                ", teacher='" + teacher + '\'' +
                ", studentList=" + studentList +
                '}';
    }

    public String getCno() {
        return cno;
    }

    public void setCno(String cno) {
        this.cno = cno;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getTeacher() {
        return teacher;
    }

    public void setTeacher(String teacher) {
        this.teacher = teacher;
    }

    public List<Student> getStudentList() {
        return studentList;
    }

    public void setStudentList(List<Student> studentList) {
        this.studentList = studentList;
    }
}
package com.openallzzz.entity;

public class Student { // 学生类

    private String id;
    private String name;
    private String sex;
    private String classno;
    private int age;

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

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getClassno() {
        return classno;
    }

    public void setClassno(String classno) {
        this.classno = classno;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
package com.openallzzz.entity.dto;

import com.openallzzz.entity.Class;
import com.openallzzz.entity.Student;

public class OneOne { // 一对一的 DTO
    private Student student;
    private com.openallzzz.entity.Class clazz;

    @Override
    public String toString() {
        return "OneOne{" +
                "student=" + student +
                ", clazz=" + clazz +
                '}';
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }
}
package com.openallzzz.entity.dto;

import com.openallzzz.entity.Class;
import com.openallzzz.entity.Student;

import java.util.List;

public class OneMany { // 一对多的 DTO

    private Class clazz;
    private List<Student> studentList;

    @Override
    public String toString() {
        return "OneMany{" +
                "clazz=" + clazz +
                ", studentList=" + studentList +
                '}';
    }

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }

    public List<Student> getStudentList() {
        return studentList;
    }

    public void setStudentList(List<Student> studentList) {
        this.studentList = studentList;
    }
}
  • 数据库以及SQL文件

教室(class)表

在这里插入图片描述

学生(student)表

在这里插入图片描述

SQL文件,放在到名为mybatis的数据库下运行查询即可,> 没有mybatis数据库的,需要先创建名为mybatis的数据库

/*
 Navicat Premium Data Transfer

 Source Server         : 127.0.0.1-MySQL8.0
 Source Server Type    : MySQL
 Source Server Version : 80026 (8.0.26)
 Source Host           : localhost:3306
 Source Schema         : mybatis

 Target Server Type    : MySQL
 Target Server Version : 80026 (8.0.26)
 File Encoding         : 65001

 Date: 25/04/2023 17:27:42
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for class
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class`  (
  `cno` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `cname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `number` int NULL DEFAULT NULL,
  `teacher` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of class
-- ----------------------------
INSERT INTO `class` VALUES ('03', '软件三班', 30, '周冲');

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `sex` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `classno` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `age` int NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('420109070226', '张宇', '男', '03', 21);
INSERT INTO `student` VALUES ('420109070212', '小明', '男', '03', 22);
INSERT INTO `student` VALUES ('420109070223', '小美', '男', '03', 20);

SET FOREIGN_KEY_CHECKS = 1;
  • 数据访问层

package com.openallzzz.dao;

import com.openallzzz.entity.Class;
import com.openallzzz.entity.Student;
import com.openallzzz.entity.dto.OneMany;
import com.openallzzz.entity.dto.OneOne;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface StudentMapper {
	// 一对一实现
    OneOne listOneToOne(String id);

    Class listOneToMany(String cno);

	// 一对多(DTO)实现
    OneMany listOneToManyByDto(String cno);
	
	// 一对多的(非DTO)实现
    List<Student> listStudentByClassno(String cno);
}

student-mapper.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.openallzzz.dao.StudentMapper">

    <select id="listStudentByClassno" resultType="student">
        select * from student where student.classno = #{cno}
    </select>

    <!--OneOne-->
    <select id="listOneToOne" parameterType="string" resultMap="OneOneMap">
        select * from student, class where student.classno = class.cno and student.id = #{id}
    </select>

    <resultMap id="OneOneMap" type="com.openallzzz.entity.dto.OneOne">
        <association property="student" javaType="student">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="sex" column="sex"/>
            <result property="classno" column="classno"/>
            <result property="age" column="age"/>
        </association>

        <association property="clazz" javaType="class">
            <result property="cno" column="cno"/>
            <result property="cname" column="cname"/>
            <result property="number" column="number"/>
            <result property="teacher" column="teacher"/>
        </association>
    </resultMap>

    <!--OneMany-->

    <!--方式一-->
    <select id="listOneToMany" parameterType="string" resultMap="OneManyMap">
        select * from class
        where class.cno = #{cno};
    </select>

    <resultMap id="OneManyMap" type="class">
        <result property="cno" column="cno"/>
        <result property="cname" column="cname"/>
        <result property="number" column="number"/>
        <result property="teacher" column="teacher"/>
        <collection property="studentList" column="{cno=cno}"
                    select="com.openallzzz.dao.StudentMapper.listStudentByClassno">
        </collection>
    </resultMap>

    <!--方式二-->
    <select id="listOneToManyByDto" resultMap="OneManyMapByDto">
        select * from class
        where class.cno = #{cno};
    </select>

    <resultMap id="OneManyMapByDto" type="oneMany">
        <association property="clazz" javaType="class">
            <result property="cno" column="cno"/>
            <result property="cname" column="cname"/>
            <result property="number" column="number"/>
            <result property="teacher" column="teacher"/>
        </association>

        <collection property="studentList" column="{cno=cno}"
                    select="com.openallzzz.dao.StudentMapper.listStudentByClassno">
        </collection>
    </resultMap>
</mapper>

mybatis的配置文件:mybatis-config.xml

<?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>

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <!--将其第一个字母变为小写作为其别名-->
        <package name="com.openallzzz.entity"/>
    </typeAliases>

    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="zhangyu"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/student-mapper.xml"/>
    </mappers>

</configuration>
  • 测试

在maven项目自带的模板的test包下创建testRelationFind测试类,由于本案例没有采用spring,我们不能自动注入StudentMapper,我们采用SqlSession获取Mapper的方式来初始化StudentMapper,在进行测试。

  1. 初始化StudentMapper
private StudentMapper studentMapper;

{
    String resource = "mybatis-config.xml";
    InputStream inputStream = null;
    try {
        inputStream = Resources.getResourceAsStream(resource);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    studentMapper = sqlSession.getMapper(StudentMapper.class);
}
  1. 编写测试一对一查询功能的测试方法
@Test
public void testOneOne() {
     System.out.println(studentMapper.listOneToOne("420109070226"));
 }
  1. 编写测试一对多查询功能的测试方法
@Test
public void testOneMany() {
	// DTO 实现
    System.out.println(studentMapper.listOneToManyByDto("03"));
    // 非 DTO 实现
    System.out.println(studentMapper.listOneToMany("03"));
}
  1. 完整的测试代码
package com.openallzzz;

import com.openallzzz.dao.StudentMapper;
import com.openallzzz.entity.Class;
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 org.junit.Test;

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

public class testRelationFind {

    private StudentMapper studentMapper;

    {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        studentMapper = sqlSession.getMapper(StudentMapper.class);
    }

    @Test
    public void testOneOne() {
        System.out.println(studentMapper.listOneToOne("420109070226"));
    }

    @Test
    public void testOneMany() {
//        System.out.println(studentMapper.listOneToManyByDto("03"));
        System.out.println(studentMapper.listOneToMany("03"));
    }
}

总结

都看到这里了,帮我点个喜欢吧🥰

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis 是一款使用 XML 或注解配置的持久层框架,它可以自动化地将数据库中的数据映射到 Java 对象中。在 MyBatis 中,mappermapper.xml 是配对使用的,其中 mapper 是接口,而 mapper.xml 是映射配置文件。 mapper 接口中定义了数据库操作的方法,而 mapper.xml 中则定义了这些方法的 SQL 语句以及参数映射规则、结果集映射规则等。 下面是一个简单的例子: 1. 定义 mapper 接口 ```java public interface UserMapper { User selectUserById(Integer id); } ``` 2. 定义 mapper.xml 映射配置文件 ```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.example.UserMapper"> <resultMap id="userResultMap" type="com.example.User"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="password" property="password"/> </resultMap> <select id="selectUserById" resultMap="userResultMap"> SELECT * FROM user WHERE id = #{id} </select> </mapper> ``` 上述代码中,namespace 属性指定了 mapper 接口的全限定名,resultMap 标签定义了一个结果集映射规则,select 标签定义了一个查询操作,其中 id 属性指定了 mapper 接口中的方法名,resultMap 属性指定了结果集映射规则的 id。 3. 在 MyBatis 配置文件中引入 mapper.xml ```xml <?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> <mappers> <mapper resource="com/example/UserMapper.xml"/> </mappers> </configuration> ``` 上述代码中,mapper 标签指定了映射配置文件的位置。 这样就完成了 mappermapper.xml配置。在代码中调用 selectUserById 方法时,MyBatis 会根据 mapper.xml 中的配置自动生成 SQL 语句,并将查询结果映射到 User 对象中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值