首页 > 其他分享 >技术框架中对高级查询环境搭建学习

技术框架中对高级查询环境搭建学习

时间:2024-12-05 19:12:38浏览次数:7  
标签:框架 int 查询 -- game id tb public 搭建

高级查询

MyBatis 高级查询

之前在学习 Mapper XML 映射文件时,说到 resultMap 标记是 MyBatis 中最重要最强大也是最复杂的标记,而且还提到后面会详细介绍它的高级用法。

听到高级用法不要觉得有多高级,说白了就是联表查询

MyBatis 支持三种联表查询方式:

  • 一对一关联查询
  • 一对多关联查询
  • 多对多关联查询

联表查询需要用到 resultMap 标记两个子标记:

  • association 标记:用于映射关联查询单个对象的信息
  • collection 标记:用于映射关联查询多个对象的信息

环境准备

创建数据库表

为了演示高级查询,我准备了四张表,想必大家都喜欢玩游戏,那么这四张表和游戏有关,分别是:

  • 玩家表(tb_player)
  • 游戏表(tb_game)
  • 账号表(tb_account)
  • 角色表(tb_role)

简单分析一下这四张表的关系如下:

  • 玩家表->游戏表:多对多(一个玩家有多个游戏,一个游戏有多个玩家)
  • 游戏表->账号表:一对多(一个游戏有多个账号,一个账号有一个游戏)
  • 账号表->角色表:一对一(一个账号有一个角色,一个角色有一个账号)

编写 SQL 语句分别创建四张表,如下:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `tb_account`
-- ----------------------------
DROP TABLE IF EXISTS `tb_account`;
CREATE TABLE `tb_account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `game_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `game_id` (`game_id`) USING BTREE,
  CONSTRAINT `tb_account_ibfk_1` FOREIGN KEY (`game_id`) REFERENCES `tb_game` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_account
-- ----------------------------
INSERT INTO `tb_account` VALUES ('1', '潇洒哥', '12345', '1');
INSERT INTO `tb_account` VALUES ('4', '进击巨人', '11111', '1');
INSERT INTO `tb_account` VALUES ('5', '征服者', '12315', '2');

-- ----------------------------
-- Table structure for `tb_game`
-- ----------------------------
DROP TABLE IF EXISTS `tb_game`;
CREATE TABLE `tb_game` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `type` varchar(255) DEFAULT NULL,
  `operator` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_game
-- ----------------------------
INSERT INTO `tb_game` VALUES ('1', '英雄联盟', 'MOBA', '腾讯游戏');
INSERT INTO `tb_game` VALUES ('2', '绝地求生', 'TPS', '蓝洞游戏');

-- ----------------------------
-- Table structure for `tb_player`
-- ----------------------------
DROP TABLE IF EXISTS `tb_player`;
CREATE TABLE `tb_player` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `sex` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_player
-- ----------------------------
INSERT INTO `tb_player` VALUES ('1', '张三', '23', '1');
INSERT INTO `tb_player` VALUES ('2', '李四', '24', '1');

-- ----------------------------
-- Table structure for `tb_player_game`
-- ----------------------------
DROP TABLE IF EXISTS `tb_player_game`;
CREATE TABLE `tb_player_game` (
  `player_id` int(11) NOT NULL DEFAULT '0',
  `game_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`player_id`,`game_id`),
  KEY `game_id` (`game_id`),
  CONSTRAINT `tb_player_game_ibfk_2` FOREIGN KEY (`game_id`) REFERENCES `tb_game` (`id`),
  CONSTRAINT `tb_player_game_ibfk_1` FOREIGN KEY (`player_id`) REFERENCES `tb_player` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_player_game
-- ----------------------------
INSERT INTO `tb_player_game` VALUES ('1', '1');
INSERT INTO `tb_player_game` VALUES ('1', '2');
INSERT INTO `tb_player_game` VALUES ('2', '2');

-- ----------------------------
-- Table structure for `tb_role`
-- ----------------------------
DROP TABLE IF EXISTS `tb_role`;
CREATE TABLE `tb_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `profession` varchar(255) DEFAULT NULL,
  `rank` int(11) DEFAULT NULL,
  `money` int(11) DEFAULT NULL,
  `account_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `account_id` (`account_id`) USING BTREE,
  CONSTRAINT `tb_role_ibfk_1` FOREIGN KEY (`account_id`) REFERENCES `tb_account` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_role
-- ----------------------------
INSERT INTO `tb_role` VALUES ('1', '战士', '10', '2000', '1');
INSERT INTO `tb_role` VALUES ('2', '法师', '30', '100000', '4');
INSERT INTO `tb_role` VALUES ('4', '刺客', '1', '100', '5');

数据库显示如下:

这张图是通过 Navicat 工具的逆向表模型功能得到的,可以直观方便查看表与表之间的关系,操作步骤如下:

你可能会问,不是说四张表,怎么数据库里有五张表呀,原因是多对多的关联关系在数据库中无法直接实现,只能间接实现;具体而言,就是通过添加一张中间表,将多对多的关联关系转化为两个一对多的关联关系。

如果还没搞明白,建议你去复习一下数据库的相关知识。

创建 Java 实体类

我们需要创建数据库四张表对应的 Java 实体类,在之前的 Maven 工程的 main/java/entity/ 下分别创建 PlayerEntity.java、GameEntity.java、AccountEntity.java、RoleEntity.java 四个文件,如下:

package entity;

/**
 * @desc 游戏玩家实体类
 * @date 2020/7/10 下午6:01
 */
public class PlayerEntity {
    private int id;
    private String name;
    private int age;
    private int sex;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getSex() {
        return sex;
    }

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

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

/**
 * @desc 游戏实体类
 * @date 2020/7/10 下午6:02
 */
public class GameEntity {
    private int id;
    private String name;
    private String type;
    private String operator;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = operator;
    }

    @Override
    public String toString() {
        return "GameEntity{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", operator='" + operator + '\'' +
                '}';
    }
}
package entity;

/**
 * @desc 游戏账号实体类
 * @date 2020/7/10 下午6:04
 */
public class AccountEntity {
    private int id;
    private String userName;
    private String password;

    public int getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "AccountEntity{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

package entity;

/**
 * @desc 游戏角色实体类
 * @date 2020/7/10 下午6:08
 */
public class RoleEntity {
    private int id;
    private String profession;
    private int rank;
    private int money;

    public int getId() {
        return id;
    }

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

    public String getProfession() {
        return profession;
    }

    public void setProfession(String profession) {
        this.profession = profession;
    }

    public int getRank() {
        return rank;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "RoleEntity{" +
                "id=" + id +
                ", profession='" + profession + '\'' +
                ", rank=" + rank +
                ", money=" + money +
                '}';
    }
}
创建映射器接口

在之前的 Maven 工程的 main/java/mapper/ 下创建 GameMapper.java 接口文件,如下:

package mapper;

import entity.RoleEntity;

/**
 * @desc 游戏映射器接口
 * @date 2020/7/10 下午6:20
 */
public interface GameMapper {
    
}

目前接口类中没有方法,后续添加查询需求时再添加对应的接口方法。

你可能会有点疑惑,之前创建了四个 Java 实体类对应四张表,为何这里只创建了一个 Java 映射器接口?是不是也应该创建四个?

MyBatis 没有必须要求一个 Java 实体类一定要对应一个 Java 映射器接口。创建多少个映射器接口,一般根据项目的可阅读性和可维护性决定的。

由于我们的查询需求比较简单,不存在可阅读性和可维护性问题,所以创建一个映射器接口就足够了。

创建 XML 映射文件

在之前的 Maven 工程的 main/resources/mappers 下创建 GameMapper.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="mapper.GameMapper">
    
</mapper>

由于映射器接口没有方法,所以映射文件也是空的。

全局配置中添加 XML 映射文件路径

在 Maven 工程中打开 main/resources/mybatis-config.xml 全局配置文件,添加之前创建的 GameMapper.xml 文件路径,如下:

		<!--配置映射文件路径-->
    <mappers>
        <mapper resource="mappers/UserMapper.xml" />
      	<!--添加 GameMapper.xml 映射文件路径-->
        <mapper resource="mappers/GameMapper.xml" />
    </mappers>

至此,基本的环境已经准备好了。

接下来,我们还需要复习一下数据库的联表查询相关的知识。

所谓联表查询指的是从数据库相关联的多张表中查询信息,数据库中联表查询的方式有两种,如下:

  • 关联查询(关键字 JOIN)

    关联查询细分为四种类型,分别为左关联(LEFT JOIN)、右关联(RIGHT JOIN)、自关联(INNER JOIN)和全关联(FULL JOIN),而直接写 JOIN 默认是自关联。关于它们之间的区别,这里我就不赘述了,搞不懂的同学,还请去复习数据库。

  • 子查询 (关键字 SELECT)

    子查询也叫嵌套查询

关联查询和子查询二者各有优缺点,如下:

  • 关联查询优缺点:优点是性能好,查询过程不产生临时表;缺点是 SQL 语句复杂,可复用性低
  • 子查询优缺点:优点是 SQL 语句简单,可复用性高;缺点是性能差,查询过程要产生临时表

实际项目开发,为了追求性能,一般多用关联查询。

既然数据库联表查询有两种方式,那么 MyBatis 的联表查询也支持这两种方式;在 MyBatis 中一对一和一对多可是使用 association 或者 collection 标记来配合实现;至于多对多,也就是两个一对多而已。

标签:框架,int,查询,--,game,id,tb,public,搭建
From: https://www.cnblogs.com/BingBing-8888/p/18589232

相关文章

  • MyBatisPlus整合mybatisplus-plus和MyBatis-Plus-Join同时支持默认的方法和多表联查加
    前情提要:在工作上的时候遇到一个情况,一个实体类没有唯一主键而是由两到三个字段组成的复合主键比如:classUser{privateStringorg;privateStringuserId;privateStringname;}在需求中这种类的主键就是org+userId来组成的联合主键,如果使用mp的话不......
  • mysql left join on条件与where条件 统计报表查询方法
    mysqlleftjoinon条件与where条件统计报表查询方法1.确定数据数量,通过简化的sql查找符合条件的订单号列表2.然后根据需求,添加单个的字段,在这个过程中会添加leftjoin左关联表查询需要区分两种情况2.1.可以唯一确定记录的,(SELECTt3.get_car_addrFROM`delivery_addr`t3W......
  • RTL difftest搭建
    difftest在测试集中可以起到十分重要的作用,可以快速找到发生问题的指令和pc寄存器地址。在nemu作为dut,参考其他模拟器(比如spike)的功能中,大部分代码已经完成,我们只需要完成寄存器的比对即可。但在RTL中重新实现这一功能或者类似功能时,我们需要完成更多函数,但大体的框架已经完成......
  • MySQL的eq_range_index_dive_limit参数对in查询影响
    目录参数说明场景复现参数说明MySQL5.7的官方说明文档:https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_eq_range_index_dive_limiteq_range_index_dive_limit变量影响优化器在等值比较的条件中,如何评估符合条件的行数。等值比较的表达式类似以......
  • 上千人挑战,用通义灵码从 0 开始打造一款 App 爆火 | 第二课:搭建本机服务
    通义灵码携手科技博主@玺哥超carry打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。上节课我们完成了从0开始打造一款App的前端代码的生成,超过1000多人参与体验互动,反响非常好!本节课我......
  • 上千人挑战,用通义灵码从 0 开始打造一款 App 爆火 | 第二课:搭建本机服务
    通义灵码携手科技博主@玺哥超carry打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。上节课我们完成了从0开始打造一款App的前端代码的生成,超过1000多人参与体验互动,反响非常好!本节课我......
  • 上千人挑战,用通义灵码从 0 开始打造一款 App 爆火 | 第二课:搭建本机服务
    通义灵码携手科技博主@玺哥超carry打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。上节课我们完成了从0开始打造一款App的前端代码的生成,超过1000多人参与体验互动,反响非常好!本节课我......
  • 【ubuntu】使用redis-cli操作redis查询
    一、场景命令行操作redis,万一没有界面化软件可用   二、文档https://redis.io/docs/latest/develop/tools/cli/  三、安装sudoapt-getupdatesudoapt-getinstallredis-tools  四、命令介绍$redis-cli--helpredis-cli7.0.15Usage:redis-cli[O......
  • vsftp搭建虚拟用户模式
    一、CentOS1.安装vsftp以及相关依赖yum-yinstallvsftpd*pam*db4*·vsftpd:ftp软件·pam:认证模块·DB4:支持文件数据库关闭selinuxsetenforce0#暂时关闭sed-ri's#(SELINUX=)enforcing#\1disabled#'/etc/selinux/config#永久关闭grep^SELINUX=/etc/selinu......
  • 模拟JUnit框架:创建自定义测试注解和运行器
    模拟JUnit框架:创建自定义测试注解和运行器引言在软件开发中,单元测试是保证代码质量的重要环节。JUnit是一个流行的Java单元测试框架,它提供了@Test注解来标记测试方法,并且有内置的机制来发现并执行这些测试。本文将通过一个简单的例子展示如何使用Java的注解和反射机制模拟JUnit......