【MyBatis】3、一文介绍如何用 MyBatis 进行多表级联查询

简介: 【MyBatis】3、一文介绍如何用 MyBatis 进行多表级联查询


一、设置新插入记录的主键(id)到参数对象中

<insert id="insert01" parameterType="Student">
    INSERT INTO student (name, money) VALUES (#{name}, #{money})
    <selectKey resultType="long" keyProperty="id" order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
</insert>

执行了两条 SQL 语句


<insert id="insert02"
         useGeneratedKeys="true"
         keyProperty="id"
         parameterType="Student">
     INSERT INTO student (name, money) VALUES (#{name}, #{money})
 </insert>

💜 只执行了一条 SQL 语句

💜 该写法需要数据库驱动支持(如:MySQL 支持,而 Oracle 不支持)

二、PageHelper 分页插件

💦 添加 MAVEN 依赖

<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.2.0</version>
</dependency>

💦 在 mybatis-config.xml 中配置插件

<plugins>
  <!-- PageHelper 插件 -->
  <!-- interceptor 拦截器 -->
  <plugin interceptor="com.github.pagehelper.PageInterceptor">
    <property name="reasonable" value="true"/>
  </plugin>
</plugins>

reasonable 设置为 true:

① 当 pageNum <= 0 的时候,会自动获取第一页的数据

② 当 pageNum > pages(总页数) 的时候,会自动获取最后一页的数据


public class TestStudent {
  @Test
    public void testPage() {
        try (SqlSession sqlSession = MyBatisUtil.openSession(true)) {
            PageHelper.startPage(1, 5);
            List<Student> list = sqlSession.selectList("student.list");
            for (Student student : list) {
                System.out.println("testPage student: " + student);
            }
        }
    }
}
<mapper namespace="student">
    <sql id="sqlListAll">
        SELECT * FROM student
    </sql>
    <resultMap id="resultMapStudent" type="com.pojo.po.Student">
        <id property="id" column="id"/>
        <result property="createTime" column="create_time"/>
    </resultMap>
    <select id="list" resultMap="resultMapStudent">
        <include refid="sqlListAll"/>
    </select>
</mapper>

三、多表关系

一对多:

一对一:

多对多:


# drop
DROP TABLE IF EXISTS bank_card;
DROP TABLE IF EXISTS id_card;
DROP TABLE IF EXISTS person_job;
DROP TABLE IF EXISTS person;
DROP TABLE IF EXISTS job;
# person
CREATE TABLE person(
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(20) NOT NULL
);
# bank_card
CREATE TABLE bank_card(
  id INT PRIMARY KEY AUTO_INCREMENT,
  no VARCHAR(30) NOT NULL UNIQUE,
  amout DECIMAL(18, 2) NOT NULL,
  person_id INT NOT NULL,
  FOREIGN KEY (person_id) REFERENCES person(id)
);
# id_card
CREATE TABLE id_card(
  id INT PRIMARY KEY AUTO_INCREMENT,
  no VARCHAR(30) NOT NULL UNIQUE,
  address VARCHAR(50) NOT NULL,
  person_id INT NOT NULL UNIQUE,
  FOREIGN KEY (person_id) REFERENCES person(id)
);
# job
CREATE TABLE job(
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(20) NOT NULL UNIQUE,
  duty VARCHAR(50) NOT NULL
);
# person_job
CREATE TABLE person_job(
  person_id INT,
  job_id INT,
  PRIMARY KEY (person_id, job_id),
  FOREIGN KEY (person_id) REFERENCES person(id),
  FOREIGN KEY (job_id) REFERENCES job(id)
);
# data
INSERT INTO person(name) VALUES ('Jack'), ('Rose'), ('Larry'), ('Mike'), ('Tom'), ('James');
INSERT INTO id_card(no, address, person_id) VALUES 
('9527', '北京', 4),
('8866', '广州', 1),
('2495', '上海', 5),
('4378', '成都', 2),
('5454', '杭州', 6),
('9923', '深圳', 3);
INSERT INTO bank_card(no, amout, person_id) VALUES 
('6223', 0, 1),
('75556', 2098.56, 2),
('5345', 1010000.56, 1),
('87876', 534423.34, 3),
('654645', 432.45, 1),
('5434534', 234765.19, 4),
('76853', 98945.39, 4),
('6456867', 435534.78, 1),
('4324654', 874343.99, 4),
('53455', 5.20, 2);
INSERT INTO job(name, duty) VALUES 
('程序员', '每一天都在写新的bug和修改昨天的bug'),
('保安', '公司全系统物理安全保障专员'),
('网管', '世界互联网信息终端及人类信息科技部信息集成应用导师'),
('厨师', '类口腔神经末梢感应实验中心及绿色环保邮寄肥转换加工基地负责人'),
('贴膜', '智能高端移动设备表面高化合物平面处理'),
('搬砖', '长方体混泥土瞬间移动师'),
('算命', '主观性逻辑推论及心理引导'),
('理发师', '人体无用副组织切除手术主刀');
INSERT INTO person_job(person_id, job_id) VALUES 
(1, 1),
(1, 3),
(1, 5),
(1, 7),
(2, 5),
(3, 1),
(3, 2),
(5, 3),
(5, 5),
(5, 7);

四、一对一

(1) 查询 person 信息, 同时查询出 person 对应的 id_card 信息

# 查询 person 信息, 同时查询出 person 对应的 id_card 信息
SELECT
  p.*,
  c.id c_id,
  c.`no` c_no,
  c.address c_address
FROM
  person p
  LEFT JOIN id_card c ON p.id = c.person_id

💦 写法1

<mapper namespace="person">
    <select id="list1" resultType="Person">
        SELECT
        p.*,
        c.id `idCard.id`,
        c.no `idCard.no`,
        c.address `idCard.address`
        FROM
        person p
        LEFT JOIN id_card c ON p.id = c.person_id
    </select>
</mapper>

自动映射到 Person 的 idCard 属性的 id、no、address 属性上面去

💦 写法2

<mapper namespace="person">
    <resultMap id="rmList2" type="Person">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!-- 映射 idCard -->
        <association property="idCard" javaType="IdCard">
            <id property="id" column="c_id"/>
            <result property="no" column="c_no"/>
            <result property="address" column="c_address"/>
        </association>
    </resultMap>
    <select id="list2" resultMap="rmList2">
        SELECT
        p.*,
        c.id c_id,
        c.`no` c_no,
        c.address c_address
        FROM
        person p
        LEFT JOIN id_card c ON p.id = c.person_id
    </select>
</mapper>

(2) 查询 id_card 信息, 同时查询出 id_card 对应的 person 信息

# 查询 id_card 信息, 同时查询出 id_card 对应的 person 信息
SELECT
  c.*,
  p.id p_id,
  p.NAME p_name 
FROM
  id_card c
  LEFT JOIN person p ON p.id = c.person_id
<mapper namespace="idCard">
    <resultMap id="rmList" type="IdCard">
        <id property="id" column="id"/>
        <result property="no" column="no"/>
        <result property="address" column="address"/>
        <!-- 映射 person -->
        <association property="person" javaType="Person">
            <id property="id" column="p_id"/>
            <result property="name" column="p_name"/>
        </association>
    </resultMap>
    <select id="list" resultMap="rmList">
        SELECT
        c.*,
        p.id p_id,
        p.NAME p_name
        FROM
        id_card c
        LEFT JOIN person p ON p.id = c.person_id
    </select>
</mapper>

五、一对多

# 查询 person 信息, 同时查询出 person 对应的 bank_card 信息
SELECT
  p.*,
  b.id bankCard_id,
  b.no bankCard_no,
  b.amout bankCard_amount
FROM
  person p
  LEFT JOIN bank_card b ON b.person_id = p.id
<mapper namespace="person">
    <resultMap id="rmListWithBankCard" type="Person">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!-- 映射 bank_card -->
        <collection property="bankCards" ofType="BankCard">
            <id property="id" column="bankCard_id"/>
            <result property="no" column="bankCard_no"/>
            <result property="amount" column="bankCard_amount"/>
        </collection>
    </resultMap>
    <select id="listWithBankCard" resultMap="rmListWithBankCard">
        SELECT
        p.*,
        b.id bankCard_id,
        b.no bankCard_no,
        b.amount bankCard_amount
        FROM
        person p
        LEFT JOIN bank_card b ON b.person_id = p.id
    </select>
</mapper>

六、多对多

查询 person 信息, 同时查询出 job 信息:

SELECT
  p.*,
  j.id job_id,
  j.`name` job_name,
  j.duty job_duty 
FROM
  person p
  LEFT JOIN person_job pj ON p.id = pj.person_id
  LEFT JOIN job j ON j.id = pj.job_id;
<mapper namespace="person">
    <resultMap id="rmListWithJob" type="Person">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="jobs" ofType="Job">
            <id property="id" column="job_id"/>
            <result property="name" column="job_name"/>
            <result property="duty" column="job_duty"/>
        </collection>
    </resultMap>
    <select id="listWithJob" resultMap="rmListWithJob">
        SELECT
        p.*,
        j.id job_id,
        j.`name` job_name,
        j.duty job_duty
        FROM
        person p
        LEFT JOIN person_job pj ON p.id = pj.person_id
        LEFT JOIN job j ON j.id = pj.job_id
    </select>
</mapper>

查询 job 列表,同时查询出从事该 job 的 person 列表:

<mapper namespace="job">
    <resultMap id="rmListWithPerson" type="Job">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="duty" column="duty"/>
        <collection property="persons" ofType="Person">
            <id property="id" column="person_id"/>
            <result property="name" column="person_name"/>
        </collection>
    </resultMap>
    <select id="listWithPerson" resultMap="rmListWithPerson">
        SELECT
        j.*,
        p.id person_id,
        p.`name` person_name
        FROM
        job j
        LEFT JOIN person_job pj ON pj.job_id = j.id
        LEFT JOIN person p ON pj.person_id = p.id;
    </select>
</mapper>
相关文章
|
8月前
|
SQL XML Java
MyBatis Mapper中使用limit参数的查询问题
总结而言,MyBatis中使用 `limit`参数的查询可以高度定制并且灵活,基于方法签名和XML映射文件的组合来达成多样化的查询需求。通过参数化查询和动态SQL,MyBatis可以有效地处理各种复杂情境下的数据库操作,并且将SQL语句的维护与业务代码的编写相分离,提升代码的可维护性和可阅读性。
678 13
|
Java 数据库连接 数据库
mybatis查询数据,返回的对象少了一个字段
mybatis查询数据,返回的对象少了一个字段
1242 9
|
9月前
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
485 1
|
XML Java 数据库连接
Mybatis一对一,一对多关联查询
## MyBatis一对一、一对多关联查询详解 MyBatis是一款优秀的持久层框架,提供了灵活的SQL映射功能,支持复杂的数据库操作。本文将详细介绍MyBatis中一对一和一对多关联查询的实现。 ### 一对一关联查询 一对一关联关系指的是一个表中的一条记录与另一个表中的一条记录相关联。例如,一个用户有一个地址信息。 #### 数据库表设计 假设有两个表:`user`和 `address`。 ``` CREATE TABLE user ( id INT PRIMARY KEY, name VARCHAR(50) ); CREATE TABLE address
460 18
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
1662 6
|
SQL Java 关系型数据库
Mybatis多表关联查询与动态SQL(下)
Mybatis多表关联查询与动态SQL
388 0
|
SQL Java 数据库连接
Mybatis多表关联查询与动态SQL(上)
Mybatis多表关联查询与动态SQL
496 0
|
SQL 缓存 Java
mybatis 一对多查询
mybatis 一对多查询
457 0
|
SQL 安全 Java
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
489 2
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
|
XML Java 数据库连接
Mybatis实现RBAC权限模型查询
通过对RBAC权限模型的理解和MyBatis的灵活使用,我们可以高效地实现复杂的权限管理功能,为应用程序的安全性和可维护性提供有力支持。
432 5