精华内容
下载资源
问答
  • MyBatis实现一对一,一对多关联查询

    万次阅读 多人点赞 2019-09-25 00:20:31
    关联查询是几个表联合查询,只查询一次,通过在resultMap里面的association,collection节点配置一对一,一对多的类就可以完成 具体实现如下 准备数据库结构与数据 班级classes与老师teacher是一对一的关系 班级...

    MyBatis如何实现一对一,一对多查询的?

    可以通过关联查询实现。关联查询是几个表联合查询,只查询一次,通过在resultMap里面的association,collection节点配置一对一,一对多的类就可以完成

    具体实现如下

    准备数据库表结构与数据

    班级classes与老师teacher是一对一的关系

    班级classes与学生student是一对多的关系

    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for classes
    -- ----------------------------
    DROP TABLE IF EXISTS `classes`;
    CREATE TABLE `classes`  (
      `c_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '班级id',
      `c_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '班级名',
      `teacher_id` int(11) NULL DEFAULT NULL COMMENT '老师id',
      PRIMARY KEY (`c_id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic COMMENT '班级表';
    
    -- ----------------------------
    -- Records of classes
    -- ----------------------------
    INSERT INTO `classes` VALUES (1, '高三2班', 1);
    INSERT INTO `classes` VALUES (2, '高一4班', 2);
    
    -- ----------------------------
    -- Table structure for teacher
    -- ----------------------------
    DROP TABLE IF EXISTS `teacher`;
    CREATE TABLE `teacher`  (
      `t_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '老师id',
      `t_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '老师姓名',
      PRIMARY KEY (`t_id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic COMMENT '老师表';
    
    -- ----------------------------
    -- Records of teacher
    -- ----------------------------
    INSERT INTO `teacher` VALUES (1, '老师张三');
    INSERT INTO `teacher` VALUES (2, '老师李四');
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for student
    -- ----------------------------
    DROP TABLE IF EXISTS `student`;
    CREATE TABLE `student`  (
      `s_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '学生id',
      `s_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '学生姓名',
      `class_id` int(11) NULL DEFAULT NULL COMMENT '班级id',
      PRIMARY KEY (`s_id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic COMMENT '学生表';
    
    -- ----------------------------
    -- Records of student
    -- ----------------------------
    INSERT INTO `student` VALUES (1, '学生小明', 1);
    INSERT INTO `student` VALUES (2, '学生小陈', 1);
    INSERT INTO `student` VALUES (3, '学生小张', 2);
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    数据库准备工作完成后,使用IDEA新建一个Spring Boot项目,工程目录如下

    新建Spring Boot项目

    在这里插入图片描述

    在pom.xml文件中添加如下依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.0</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    

    在application.yml文件中进行数据库和mybatis配置

    # spring配置
    spring:
      # 数据库配置
      datasource:
        type: com.zaxxer.hikari.HikariDataSource
        url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true&useSSL=false&tinyInt1isBit=false&serverTimezone=GMT%2B8
        driverClassName: com.mysql.cj.jdbc.Driver
        username: root
        password: root
    
    # mybatis配置
    mybatis:
      # 给实体类配置别名
      type-aliases-package: com.jourwon.*.pojo
      # 加载mybatis的mapper配置文件
      mapper-locations: classpath:mybatis/mapper/**/*Mapper.xml
      configuration:
        # 开发环境控制台打印sql语句
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
        # 开启驼峰规则自动映射字段属性值;如字段为user_name的可以映射到userName属性中
        map-underscore-to-camel-case: true
        # 设置sql执行超时时间,以秒为单位的全局sql超时时间设置,当超出了设置的超时时间时,会抛出SQLTimeoutException
        default-statement-timeout: 30
        # 解决查询返回结果含null没有对应字段值问题
        call-setters-on-nulls: true
    

    新建老师类Teacher

    @Data
    public class Teacher {
    
        private int id;
    
        private String name;
    
    }
    

    新建班级类Classes

    @Data
    public class Classes {
    
        private int id;
    
        private String name;
    
        private Teacher teacher;
    
        private List<Student> studentList;
    
    
    }
    

    新建学生类Student

    @Data
    public class Student {
    
        private int id;
    
        private String name;
    
    }
    

    新建ClassesMapper.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.jourwon.mybatis.mapper.ClassesMapper">
    
        <!-- 一对一关联查询 -->
        <select id="listClasses" parameterType="int" resultMap="ClassesResultMap">
    		select * from classes c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
    	</select>
    
        <resultMap type="com.jourwon.mybatis.pojo.Classes" id="ClassesResultMap">
            <!-- 实体类的字段名和数据表的字段名映射 -->
            <id property="id" column="c_id"/>
            <result property="name" column="c_name"/>
            <association property="teacher" javaType="com.jourwon.mybatis.pojo.Teacher">
                <id property="id" column="t_id"/>
                <result property="name" column="t_name"/>
            </association>
        </resultMap>
    
        <!-- 一对多关联查询 -->
        <select id="listClasses2" parameterType="int" resultMap="ClassesResultMap2">
    		select * from classes c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id}
    	</select>
    
        <resultMap type="com.jourwon.mybatis.pojo.Classes" id="ClassesResultMap2">
            <id property="id" column="c_id"/>
            <result property="name" column="c_name"/>
            <association property="teacher" javaType="com.jourwon.mybatis.pojo.Teacher">
                <id property="id" column="t_id"/>
                <result property="name" column="t_name"/>
            </association>
            <collection property="studentList" ofType="com.jourwon.mybatis.pojo.Student">
                <id property="id" column="s_id"/>
                <result property="name" column="s_name"/>
            </collection>
        </resultMap>
    
    
    </mapper>
    

    Application类

    @MapperScan(basePackages = {"com.jourwon.mybatis.**.mapper"})
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
    }
    

    测试类

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class ApplicationTests {
    
        @Autowired
        private ClassesMapper classesMapper;
    
        /**
         * Description: 测试班级与老师一对一关联关系
         *
         * @author JourWon
         * @date 2019/9/24 23:18
         * @param 
         * @return void
         */
        @Test
        public void test01() {
    
            List<Classes> classes = classesMapper.listClasses(1);
            for (Classes aClass : classes) {
                System.out.println(classes);
            }
    
        }
    
        /**
         * Description: 测试班级与学生一对多关联关系
         *
         * @author JourWon
         * @date 2019/9/24 23:19
         * @param 
         * @return void
         */
        @Test
        public void test02() {
    
            List<Classes> classes = classesMapper.listClasses2(1);
            for (Classes aClass : classes) {
                System.out.println(classes);
            }
    
        }
    
    }
    

    测试结果

    test01()测试结果输出

    ==>  Preparing: select * from classes c,teacher t where c.teacher_id=t.t_id and c.c_id=? 
    ==> Parameters: 1(Integer)
    <==    Columns: c_id, c_name, teacher_id, t_id, t_name
    <==        Row: 1, 高三2, 1, 1, 老师张三
    <==      Total: 1
    Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@140d1230]
    [Classes(id=1, name=高三2, teacher=Teacher(id=1, name=老师张三), studentList=null)]
    

    test02()测试结果输出

    ==>  Preparing: select * from classes c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=? 
    ==> Parameters: 1(Integer)
    <==    Columns: c_id, c_name, teacher_id, t_id, t_name, s_id, s_name, class_id
    <==        Row: 1, 高三2, 1, 1, 老师张三, 1, 学生小明, 1
    <==        Row: 1, 高三2, 1, 1, 老师张三, 2, 学生小陈, 1
    <==      Total: 2
    Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@140d1230]
    [Classes(id=1, name=高三2, teacher=Teacher(id=1, name=老师张三), studentList=[Student(id=1, name=学生小明), Student(id=2, name=学生小陈)])]
    

    所以,一对一关联查询需要在resultMap里面配置association,一对多关联查询需要在resultMap里面配置collection节点

    展开全文
  • 分页查询是后台项目中最常见的一种操作,在一对多(one to many)的关系中,如何根据主进行分页是一个较为棘手的问题,尤其是查询条件既包含主又包含从/关联表的。一般情况下,不是查询结果条数不正确,就是...

    1 摘要

    分页查询是后台项目中最常见的一种操作,在一对多(one to many)的关系表中,如何根据主表进行分页是一个较为棘手的问题,尤其是查询条件既包含主表又包含从表/关联表的。一般情况下,不是查询结果条数不正确,就是一对多中的多的一方只能显示一条信息。本文将记录作者自己在项目中针对一对多分页查询主表和关联表都有查询条件的一种解决方案。

    关于分页查询,也可参考作者之前的笔记:

    mysql多表联合查询分页查询结果条数错误问题

    2 情景复现

    2.1 数据模型

    在先前的分页查询笔记中使用的是用户-用户图像这一简单的一对多模型,在本次示例中使用另一种更加复杂一些的模型,多对多模型: 文章与标签模型。

    一篇文章可以对应多个标签,同时一个标签也可以对应多篇文章。不过这里依旧以文章为主表。

    文章表:

    CREATE TABLE `article` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '文章 id,主键',
      `title` varchar(100) NOT NULL DEFAULT '' COMMENT '文章标题',
      `content` text  NOT NULL COMMENT '文章内容',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文章表';
    

    标签表:

    CREATE TABLE `article_tag` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '文章标签 id,主键',
      `tag_name` varchar(20) NOT NULL DEFAULT '' COMMENT '标签名称',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文章标签表';
    
    

    在多对多关系中,建议使用中间表进行关联

    文章与标签的关联表:

    CREATE TABLE `article_to_tag` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '文章-标签中间表',
      `article_id` bigint(20) NOT NULL COMMENT '文章 id',
      `tag_id` bigint(20) NOT NULL COMMENT '标签 id',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文章-标签关联表';
    

    2.2 核心代码

    由于在前边的笔记中已经介绍过一对多分页查询的方式: 使用子查询,因此这里就直接进入正题,不再演示不合理或者说错误的查询方法。

    需求: 根据条件查询文章,该条件既包含主表的字段,也(可能)包含子表的字段,要求使用分页查询

    统计查询结果总条数:

    SELECT COUNT(DISTINCT(a.id))
    FROM `article` a 
    LEFT JOIN `article_to_tag` att ON att.article_id = a.id 
    LEFT JOIN `article_tag` at ON at.id = att.tag_id
    WHERE a.id > 2
        AND at.tag_name LIKE CONCAT(CONCAT('%', '级'),'%')
    
    

    分页查询结果:

    SELECT 
      a.id, a.title, a.content, at.tag_name
    FROM (
        SELECT item_a.*
    		FROM `article` item_a
    		LEFT JOIN `article_to_tag` item_att ON item_att.article_id = item_a.id 
    		LEFT JOIN `article_tag` item_at ON item_at.id = item_att.tag_id
    		WHERE item_a.id > 2
            AND item_at.tag_name LIKE CONCAT(CONCAT('%', '级'),'%')
    		GROUP BY item_a.id
    		ORDER BY item_a.id DESC
    		LIMIT 0,5
    ) a 
    LEFT JOIN `article_to_tag` att ON att.article_id = a.id 
    LEFT JOIN `article_tag` at ON at.id = att.tag_id
    GROUP BY a.id, at.id
    ORDER BY a.id DESC
    
    

    这里演示的SQL中查询条件为: 文章的 id > 2,同时文章的标题中包含 「级」

    注意事项: 这里的子查询只是将查询总结果按照需要的方式排列,但是实际返回到前端的数据依然需要进行排序和分组,否则,依然会出现查询结果不符合要求的情况。即内层子查询和外层查询都需要进行排序和分组

    统计条数的查询结果为:

    4
    

    分页查询结果为:

    分页查询结果
    从结果总可以看出 id 为 5,6,7,8 的文章满足以上要求

    以上便是分页查询一对多主表子表都有查询条件的解决方案

    2.3 测试数据

    本示例中演示的测试数据,感兴趣的可以自行实践

    文章标签数据:

    -- 批量插入文章标签
    INSERT INTO `article_tag`(`tag_name`) VALUES
        ('初级'),
    		('中级'),
    		('高级'),
    		('超高级'),
    		('spring'),
    		('springBoot'),
    		('springMVC');
    

    文章表数据:

    -- 批量插入文章
    INSERT INTO `article` (`title`, `content`) VALUES
        ('好风光', '今天天气好晴朗,处处好风光'),
    		('冰雨', '冷冷的冰雨在我脸上胡乱地拍,你就像一个刽子手把我出卖'),
    		('学习', '好好学习,天天向上'),
    		('静夜思', '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'),
    		('冬日里的一把火', '你就像那一把火,熊熊火焰燃烧了我'),
    		('演员', '简单点,说话的方式简单点。递进的情绪请省略,你又不是个演员'),
    		('小苹果', '你是我的小丫小苹果,怎么爱你都不嫌多'),
    		('雨一直下', '雨一直下,气氛不算融洽');
    

    文章与标签关联数据:

    -- 批量给文章添加标签
    INSERT INTO `article_to_tag` (`article_id`, `tag_id`) VALUES
        (1,1),
        (1,2),
        (1,4),
        (2,3),
        (2,5),
        (3,6),
        (4,7),
        (5,1),
        (5,2),
        (5,3),
        (6,4),
        (6,1),
        (6,5),
        (6,7),
        (7,6),
        (7,1),
        (8,3),
        (8,6),
        (8,7),
        (8,4);
    

    2.4 拓展一点

    文章通常有用户进行收藏,而在查询文章时,也可以显示文章的收藏量数据(这个需求是正常需求)

    文章的收藏量不同于文章的阅读量,文章的阅读量可以用一个字段就能够实现,有用户点增加值即可,但是用户收藏就不一样,因为用户可以查询到自己收藏的内容,这是一个正常的需求,反过来,某一篇文章被哪些用户收藏,这一功能也是可以实现的(不过这个需求个人感觉有些过分,有泄露隐私的嫌疑)

    OK,既然要实现用户收藏文章这一功能,就需要专门创建一个用户文章收藏表。

    用户文章收藏表:

    CREATE TABLE `article_user_favorite` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户收藏表id',
      `user_id` bigint(20) NOT NULL COMMENT '用户 id',
      `article_id` bigint(20) NOT NULL COMMENT '文章 id',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户文章收藏表';
    

    插入一些测试数据:

    -- 批量收藏文章
    INSERT INTO `article_user_favorite`(`user_id`, `article_id`) VALUES
        (1,1),
    		(1,2),
    		(1,3),
    		(1,4),
    		(1,5),
    		(1,6),
    		(1,7),
    		(1,8),
    		(2,1),
    		(3,1),
    		(4,1),
    		(2,2),
    		(2,6),
    		(3,1),
    		(4,1),
    		(5,1),
    		(3,2),
    		(3,6),
    		(3,7),
    		(4,8),
    		(4,5),
    		(5,2),
    		(5,3),
    		(5,4),
    		(5,5),
    		(5,6),
    		(5,7),
    		(5,8),
    		(4,4),
    		(3,3);
    
    

    还是按照上边的查询条件: 文章 id > 2, 文章的标签包含「级」
    这里需要显示每一篇文章的收藏量

    查询SQL:

    SELECT 
      a.id, a.title, a.content, at.tag_name,
    	COUNT(auf.id) AS countUserFavorite
    FROM (
        SELECT item_a.*
    		FROM `article` item_a
    		LEFT JOIN `article_to_tag` item_att ON item_att.article_id = item_a.id 
    		LEFT JOIN `article_tag` item_at ON item_at.id = item_att.tag_id
    		WHERE item_a.id > 2
            AND item_at.tag_name LIKE CONCAT(CONCAT('%', '级'),'%')
    		GROUP BY item_a.id
    		ORDER BY item_a.id DESC
    		LIMIT 0,5
    ) a 
    LEFT JOIN `article_to_tag` att ON att.article_id = a.id 
    LEFT JOIN `article_tag` at ON at.id = att.tag_id
    LEFT JOIN `article_user_favorite` auf ON auf.article_id = a.id
    GROUP BY a.id, at.id
    ORDER BY a.id DESC
    

    查询结果:

    查询结果-2

    个人公众号:404Code,记录半个互联网人的技术与思考,感兴趣的可以关注.
    404Code

    展开全文
  • Mybatis的多表关联查询一对一、一对多)

    千次阅读 多人点赞 2021-02-12 21:55:24
    Mybatis的多表关联查询mybatis中的多表查询数据库准备项目目录一对一查询(多对一)方式一(通过Accunt的子类方式查询--不常用)定义账户信息的实体类编写 Sql 语句定义 AccountUser 类定义账户的持久层 Dao 接口定义 ...

    mybatis中的多表查询

    表之间的关系有几种:
    	一对多
    	多对一
    	一对一
    	多对多
    举例: 
    	用户和订单就是一对多
    	订单和用户就是多对一
    		一个用户可以下多个订单
    		多个订单属于同一个用户
    
    	人和身份证号就是一对一
    		一个人只能有一个身份证号
    		一个身份证号只能属于一个人
    
    	老师和学生之间就是多对多
    		一个学生可以被多个老师教过
    		一个老师可以交多个学生
    特例:
    	如果拿出每一个订单,他都只能属于一个用户。
    	所以Mybatis就把多对一看成了一对一。
    	
    	mybatis中的多表查询:
    	示例:用户和账户
    		一个用户可以有多个账户
    		一个账户只能属于一个用户(多个账户也可以属于同一个用户)
    	步骤:
    		1、建立两张表:用户表,账户表
    			让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
    		2、建立两个实体类:用户实体类和账户实体类
    			让用户和账户的实体类能体现出来一对多的关系
    		3、建立两个配置文件
    			用户的配置文件
    			账户的配置文件
    		4、实现配置:
    			当我们查询用户时,可以同时得到用户下所包含的账户信息
    			当我们查询账户时,可以同时得到账户的所属用户信息
    

    数据库准备

    sql文件在这篇文章中:Mybatis 框架快速入门(超详细)
    在这里插入图片描述
    在这里插入图片描述

    项目目录

    在这里插入图片描述

    一对一查询(多对一)

    需求:
    查询所有账户,同时还要获取当前账户的所属用户信息。
    注意:
    因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户。

    方式一(通过Accunt的子类方式查询–不常用)

    定义账户信息的实体类

    Account:

    package com.keafmd.domain;
    
    import java.io.Serializable;
    
    /**
     * Keafmd
     *
     * @ClassName: Account
     * @Description:
     * @author: 牛哄哄的柯南
     * @date: 2021-02-10 21:43
     */
    public class Account implements Serializable {
        private Integer id;
        private Integer uid;
        private Double money;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public Integer getUid() {
            return uid;
        }
    
        public void setUid(Integer uid) {
            this.uid = uid;
        }
    
        public Double getMoney() {
            return money;
        }
    
        public void setMoney(Double money) {
            this.money = money;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "id=" + id +
                    ", uid=" + uid +
                    ", money=" + money +
                    '}';
        }
    }
    
    

    编写 Sql 语句

    实现查询账户信息时,也要查询账户所对应的用户信息。

    select a.*,u.username,u.address from account a ,user u where a.uid=u.id;
    

    查询结果:
    在这里插入图片描述

    select u.*,a.id as aid,a.uid,a.money from account a ,user u where a.uid=u.id;
    

    查询结果:
    在这里插入图片描述

    定义 AccountUser 类

    为了能够封装上面 SQL 语句的查询结果,定义 AccountCustomer 类中要包含账户信息同时还要包含用户信息,所以我们要在定义 AccountUser 类时可以继承 User 类。

    package com.keafmd.domain;
    
    /**
     * Keafmd
     *
     * @ClassName: AccountUser
     * @Description:
     * @author: 牛哄哄的柯南
     * @date: 2021-02-10 22:15
     */
    public class AccountUser extends Account{
    
        private String username;
        private String address;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return super.toString()+"  AccountUser{" +
                    "username='" + username + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    

    定义账户的持久层 Dao 接口

    IAccountDao:

    package com.keafmd.dao;
    
    import com.keafmd.domain.Account;
    import com.keafmd.domain.AccountUser;
    
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: IAccountDao
     * @Description:
     * @author: 牛哄哄的柯南
     * @date: 2021-02-10 21:46
     */
    
    public interface IAccountDao {
     
        /**
         * 查询账户,并且带有用户名称和地址信息
         * @return
         */
        List<AccountUser> findAllAccount();
    }
    
    

    定义 IAccountDao.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.keafmd.dao.IAccountDao">
    
        <!--查询所有,同时包含用户名和地址信息-->
        <select id="findAllAccount" resultType="accountuser">
            select a.*,u.username,u.address from account a ,user u where a.uid=u.id;
        </select>
    
    </mapper>
    

    注意:因为上面查询的结果中包含了账户信息同时还包含了用户信息,所以我们的返回值类型 returnType的值设置为 AccountUser 类型,这样就可以接收账户信息和用户信息了。

    测试代码

    package com.keafmd.test;
    
    import com.keafmd.dao.IAccountDao;
    import com.keafmd.dao.IUserDao;
    import com.keafmd.domain.Account;
    import com.keafmd.domain.AccountUser;
    import com.keafmd.domain.User;
    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.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: MybatisTest
     * @Description: 测试类,测试crud操作
     * @author: 牛哄哄的柯南
     * @date: 2021-02-08 15:24
     */
    public class AccountTest {
    
        private InputStream in;
        private SqlSession sqlsession;
        private IAccountDao accountDao;
    
        @Before // 用于在测试方法执行前执行
        public void init()throws Exception{
            //1.读取配置文件,生成字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
            //3.使用工厂生产SqlSession对象
            sqlsession = factory.openSession(); //里面写个true,下面每次就不用了写 sqlsession.commit(); 了
            //4.使用SqlSession创建Dao接口的代理对象
            accountDao = sqlsession.getMapper(IAccountDao.class);
        }
    
        @After // 用于在测试方法执行后执行
        public void destory() throws Exception{
            //提交事务
            sqlsession.commit();
            //6.释放资源
            sqlsession.close();
            in.close();
        }
    
    
        /**
         * 查询账户,并且带有用户名称和地址信息
         * @throws Exception
         */
        @Test
        public void testfindAllAccount(){
            List<AccountUser> accountusers = accountDao.findAllAccount();
            for (AccountUser accountuser : accountusers) {
                System.out.println(accountuser);
            }
        }
    
    }
    

    运行testfindAllAccount()的结果:

    在这里插入图片描述

    方式二(建立实体类关系的方式–常用)

    使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。
    通过面向对象的(has a)关系可以得知,我们可以在 Account 类中加入一个 User 类的对象来代表这个账户是哪个用户的。

    修改 Account 类

    Account:

    package com.keafmd.domain;
    
    import java.io.Serializable;
    
    /**
     * Keafmd
     *
     * @ClassName: Account
     * @Description:
     * @author: 牛哄哄的柯南
     * @date: 2021-02-10 21:43
     */
    public class Account implements Serializable {
        private Integer id;
        private Integer uid;
        private Double money;
    
        //从表实体应该包含一个主表实体的对象引用
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public Integer getUid() {
            return uid;
        }
    
        public void setUid(Integer uid) {
            this.uid = uid;
        }
    
        public Double getMoney() {
            return money;
        }
    
        public void setMoney(Double money) {
            this.money = money;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "id=" + id +
                    ", uid=" + uid +
                    ", money=" + money +
                    '}';
        }
    }
    

    修改 AccountDao 接口中的方法

    package com.keafmd.dao;
    
    import com.keafmd.domain.Account;
    import com.keafmd.domain.AccountUser;
    
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: IAccountDao
     * @Description:
     * @author: 牛哄哄的柯南
     * @date: 2021-02-10 21:46
     */
    
    public interface IAccountDao {
        /**
         * 查询所有账户,同时还要获取当前账户的所属用户信息 方法二
         * @return
         */
        List<Account> findAll();
    
    }
    

    将返回值改 为了 Account 类型,因为 Account 类中包含了一个 User 类的对象,它可以封装账户所对应的用户信息。

    重新定义 IAccountDao.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.keafmd.dao.IAccountDao">
        
        <!--定义封装account和user的resultmap-->
        <resultMap id="accountUserMap" type="account">
            <id property="id" column="aid"></id>
            <result property="uid" column="uid"></result>
            <result property="money" column="money"></result>
    
            <!--一对一的关系映射,配置封装user的内容-->
            <association property="user" column="uid" javaType="user">
                <id property="id" column="id"></id>
                <result column="username" property="username"></result>
                <result column="address" property="address"></result>
                <result column="sex" property="sex"></result>
                <result column="birthday" property="birthday"></result>
            </association>
        </resultMap>
    
        <!--配置查询所有-->
        <select id="findAll" resultMap="accountUserMap">
            select u.*,a.id as aid,a.uid,a.money from account a ,user u where a.uid=u.id;
        </select>
    
    </mapper>
    

    测试代码

    package com.keafmd.test;
    
    import com.keafmd.dao.IAccountDao;
    import com.keafmd.dao.IUserDao;
    import com.keafmd.domain.Account;
    import com.keafmd.domain.AccountUser;
    import com.keafmd.domain.User;
    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.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: MybatisTest
     * @Description: 测试类,测试crud操作
     * @author: 牛哄哄的柯南
     * @date: 2021-02-08 15:24
     */
    public class AccountTest {
    
        private InputStream in;
        private SqlSession sqlsession;
        private IAccountDao accountDao;
    
        @Before // 用于在测试方法执行前执行
        public void init()throws Exception{
            //1.读取配置文件,生成字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
            //3.使用工厂生产SqlSession对象
            sqlsession = factory.openSession(); //里面写个true,下面每次就不用了写 sqlsession.commit(); 了
            //4.使用SqlSession创建Dao接口的代理对象
            accountDao = sqlsession.getMapper(IAccountDao.class);
        }
    
        @After // 用于在测试方法执行后执行
        public void destory() throws Exception{
            //提交事务
            sqlsession.commit();
            //6.释放资源
            sqlsession.close();
            in.close();
        }
    
    
    
        /**
         * 查询所有
         * @throws Exception
         */
        @Test
        public void testFindAll() {
            List<Account> accounts = accountDao.findAll();
            for (Account account : accounts) {
                System.out.println("------------每个account的信息-------");
                System.out.println(account);
                System.out.println(account.getUser());
            }
        }
    
    }
    

    运行结果:
    在这里插入图片描述

    一对多查询

    需求:
    查询所有用户,同时获取到用户下所有账户的信息。
    分析:
    用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,我们想到了左外连接查询比较合适。

    编写User实体类

    User:

    package com.keafmd.domain;
    
    import java.io.Serializable;
    import java.util.Date;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: User
     * @Description:
     * @author: 牛哄哄的柯南
     * @date: 2021-02-08 15:16
     */
    
    public class User implements Serializable {
        private Integer id;
        private String username;
        private String sex;
        private String address;
        private Date birthday;
    
        //一对多关系映射,主表实体应该包含从表实体的集合引用
        private List<Account> accounts;
    
        public List<Account> getAccounts() {
            return accounts;
        }
    
        public void setAccounts(List<Account> accounts) {
            this.accounts = accounts;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", sex='" + sex + '\'' +
                    ", address='" + address + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    }
    

    编写 SQL 语句

    select u.* ,a.id as aid,a.uid,a.money from user u left outer join account a on u.id =a.uid
    

    执行结果:
    在这里插入图片描述

    用户持久层 Dao 接口

    IUserDao:

    package com.keafmd.dao;
    
    import com.keafmd.domain.User;
    
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: IUserDao
     * @Description: 用户的持久层接口
     * @author: 牛哄哄的柯南
     * @date: 2021-02-06 19:29
     */
    
    public interface IUserDao {
        /**
         * 查询所有用户,同时获取到用户下所有账户的信息
         * @return
         */
        List<User> findAll();
    
    }
    

    用户持久层 Dao 映射文件配置

    <?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.keafmd.dao.IUserDao">
    
        <!--定义User的resultMap-->
        <resultMap id="userAccountMap" type="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="address" column="address"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
            <!--配置user对象中account集合的映射-->
            <collection property="accounts" ofType="account">
                <id column="aid" property="id"></id>
                <result column="uid" property="uid"></result>
                <result column="money" property="money"></result>
            </collection>
        </resultMap>
    
        <!--配置查询所有-->
        <select id="findAll" resultMap="userAccountMap">
            select u.* ,a.id as aid,a.uid,a.money from user u left outer join account a on u.id =a.uid
    
        </select>
    
    </mapper>
    

    测试代码

    package com.keafmd.test;
    
    import com.keafmd.dao.IAccountDao;
    import com.keafmd.dao.IUserDao;
    import com.keafmd.domain.Account;
    import com.keafmd.domain.AccountUser;
    import com.keafmd.domain.User;
    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.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: MybatisTest
     * @Description: 测试类,测试crud操作
     * @author: 牛哄哄的柯南
     * @date: 2021-02-08 15:24
     */
    public class UserTest {
    
        private InputStream in;
        private SqlSession sqlsession;
        private IUserDao userDao;
    
        @Before // 用于在测试方法执行前执行
        public void init()throws Exception{
            //1.读取配置文件,生成字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
            //3.使用工厂生产SqlSession对象
            sqlsession = factory.openSession(); //里面写个true,下面每次就不用了写 sqlsession.commit(); 了
            //4.使用SqlSession创建Dao接口的代理对象
            userDao = sqlsession.getMapper(IUserDao.class);
        }
    
        @After // 用于在测试方法执行后执行
        public void destory() throws Exception{
            //提交事务
            sqlsession.commit();
            //6.释放资源
            sqlsession.close();
            in.close();
        }
    
    
    
        /**
         * 查询所有
         * @throws Exception
         */
        @Test
        public void testFindAll() {
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println("--------每个用户的信息---------");
                System.out.println(user);
                System.out.println(user.getAccounts());
            }
        }
    
    }
    

    运行结果:

    2021-02-12 23:14:27,911 278    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
    2021-02-12 23:14:28,402 769    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 1783047508.
    2021-02-12 23:14:28,405 772    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6a472554]
    2021-02-12 23:14:28,410 777    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - ==>  Preparing: select u.* ,a.id as aid,a.uid,a.money from user u left outer join account a on u.id =a.uid
    2021-02-12 23:14:28,453 820    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - ==> Parameters: 
    2021-02-12 23:14:28,481 848    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - <==      Total: 10
    --------每个用户的信息---------
    User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}
    [Account{id=1, uid=41, money=1000.0}, Account{id=3, uid=41, money=2000.0}]
    --------每个用户的信息---------
    User{id=42, username='update', sex='男', address='XXXXXXX', birthday=Mon Feb 08 19:37:31 CST 2021}
    []
    --------每个用户的信息---------
    User{id=43, username='小二王', sex='女', address='北京', birthday=Sun Mar 04 11:34:34 CST 2018}
    []
    --------每个用户的信息---------
    User{id=45, username='新一', sex='男', address='北京', birthday=Sun Mar 04 12:04:06 CST 2018}
    [Account{id=2, uid=45, money=1000.0}]
    --------每个用户的信息---------
    User{id=50, username='Keafmd', sex='男', address='XXXXXXX', birthday=Mon Feb 08 15:44:01 CST 2021}
    []
    --------每个用户的信息---------
    User{id=51, username='update DAO', sex='男', address='XXXXXXX', birthday=Tue Feb 09 11:31:38 CST 2021}
    []
    --------每个用户的信息---------
    User{id=52, username='Keafmd DAO', sex='男', address='XXXXXXX', birthday=Tue Feb 09 11:29:41 CST 2021}
    []
    --------每个用户的信息---------
    User{id=53, username='Keafmd laset insertid 1', sex='男', address='XXXXXXX', birthday=Fri Feb 12 20:53:46 CST 2021}
    []
    --------每个用户的信息---------
    User{id=54, username='Keafmd laset insertid 2 auto', sex='男', address='XXXXXXX', birthday=Fri Feb 12 21:02:12 CST 2021}
    []
    2021-02-12 23:14:28,483 850    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6a472554]
    2021-02-12 23:14:28,484 851    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@6a472554]
    2021-02-12 23:14:28,484 851    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 1783047508 to pool.
    
    Process finished with exit code 0
    

    以上就是Mybatis的多表关联查询(一对一、一对多)的全部内容。

    看完如果对你有帮助,感谢点赞支持!
    如果你是电脑端的话,看到右下角的 “一键三连” 了吗,没错点它[哈哈]

    在这里插入图片描述

    加油!

    共同努力!

    Keafmd

    展开全文
  • mybatis实现多表一对一,一对多,多对多关联查询

    万次阅读 多人点赞 2018-02-03 15:40:08
    1、一对一 关键字:association 作用:针对pojo对象属性的映射  property:pojo的属性名  javaType:pojo类名 (1) 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集 <!-- 1、...
    1、一对一
    关键字:association
    作用:针对pojo对象属性的映射
          property:pojo的属性名
          javaType:pojo类名
    (1) 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
    <resultMap type="com.gec.domain.Person" id="basePersonResultMap">
      	<id column="id" property="personId"/>
      	<result column="name" property="name"/>
      	<result column="sex" property="sex"/>
      	<result column="age" property="age"/>
    	
      	<association property="card" javaType="com.gec.domain.Card">
      		<!-- 1、构造器注入
    		<constructor>
      			<idArg column="id" javaType="int"/>
      			<arg column="code" javaType="string"/>
      		</constructor> 
    		-->
    		<!-- 2、setter注入 -->
      		<result column="id" property="cardId"/>
      		<result column="code" property="code"/>
      	</association>
     </resultMap>
      <select id="queryUserList" resultMap="basePersonResultMap">
      	select p.id as personId,p.name,p.sex,p.age,c.*
      	from tbl_person p,tbl_card c where p.card_id=c.id;
      </select> 
    (2) 嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
        column="引入执行另外定制sql方法的参数值(外键)"
        select="执行定制sql方法名"
    PersonMapper2.xml
    <resultMap type="com.gec.domain.Person" id="basePersonResultMap">
      	<id column="id" property="personId"/>
      	<result column="name" property="name"/>
      	<result column="sex" property="sex"/>
      	<result column="age" property="age"/>
      	<association property="card" 
      		javaType="com.gec.domain.Card"
      		column="card_id" 
      		select="com.gec.mapper.CardMapper.queryCardById">
      	</association>
    </resultMap>
    <select id="queryUserList" resultMap="basePersonResultMap">
    	select * from tbl_person;
    </select>
    CardMapper.xml
    <resultMap type="com.gec.domain.Card" id="baseCardResultMap">
      	<id column="card_id" property="cardId"/>
      	<result column="code" property="code"/>
    </resultMap>
    <select id="queryCardById" resultMap="baseCardResultMap">
      	select c.id as card_id,c.code from tbl_card c 
    	where c.id=#{id};
    </select>
    <resultMap type="com.gec.domain.Card" id="queryCardResultMap" extends="baseCardResultMap">
    	<association property="person" javaType="com.gec.domain.Person">
      		<id column="card_id" property="personId"/>
      		<result column="name" property="name"/>
      		<result column="sex" property="sex"/>
      		<result column="age" property="age"/>
      	</association>
    </resultMap>
    <select id="queryCardList" resultMap="queryCardResultMap">
    	SELECT c.id AS card_id, c.code, p.* 
      	FROM tbl_card c,tbl_person p WHERE c.id=p.card_id;
    </select>
    2 、一对多
    mybatis如何实现一对多的实现?(学生与班级)
    (1) 嵌套结果:
    ClazzMapper.xml
    <resultMap type="com.gec.domain.Clazz" id="baseClazzResultMap">
    	<id column="id" property="clazzId"/>
    	<result column="clazz_name" property="clazzName"/>
    	<result column="code" property="code"/>
    </resultMap>
    <resultMap type="com.gec.domain.Clazz" id="queryClazzList2ResultMap" extends="baseClazzResultMap">
    	<collection property="studentList" javaType="ArrayList" ofType="com.gec.domain.Student">
    		<id column="stu_id" property="studentId"/>
    		<result column="name" property="name"/>
    		<result column="sex" property="sex"/>
    		<result column="age" property="age"/>
    	</collection>
    </resultMap>
    <select id="queryClazzList2" resultMap="queryClazzList2ResultMap">
    	SELECT c.*, s.id AS stu_id,s.name,s.sex,s.age
    	FROM tbl_clazz c LEFT JOIN tbl_student s
    	ON c.id=s.clazz_id;
    </select>
    StudentMapper.xml
    <resultMap type="com.gec.domain.Student" id="baseStudentResultMap">
    	<id column="id" property="studentId"/>
    	<result column="name" property="name"/>
    	<result column="sex" property="sex"/>
    	<result column="age" property="age"/>
    </resultMap> 
    <resultMap type="com.gec.domain.Student" id="queryStudentListResultMap" extends="baseStudentResultMap">
    	<association property="clazz" javaType="com.gec.domain.Clazz">
    		<id column="cls_id" property="clazzId"/>
    		<result column="clazz_name" property="clazzName"/>
    		<result column="code" property="code"/>
    	</association>
    </resultMap> 
    <select id="queryStudentList" resultMap="queryStudentListResultMap">
    	SELECT s.*,c.id AS cls_id,c.clazz_name,c.code
    	FROM tbl_student s,tbl_clazz c WHERE s.clazz_id=c.id;
    </select>
    (2) 嵌套查询:
    ClazzMapper.xml
    <resultMap type="com.gec.domain.Clazz" id="baseClazzResultMap">
    	<id column="id" property="clazzId"/>
    	<result column="clazz_name" property="clazzName"/>
    	<result column="code" property="code"/>
    </resultMap>
    <resultMap type="com.gec.domain.Clazz" id="queryClazzListResultMap" extends="baseClazzResultMap">
    	<collection property="studentList" javaType="ArrayList" 
    		column="id" ofType="com.gec.domain.Student" 
    		select="com.gec.mapper.StudentMapper.queryStudentByClazzId"
    	>
    	</collection>
    </resultMap>
    <select id="queryClazzList" resultMap="queryClazzListResultMap">
    	select * from tbl_clazz;
    </select>
    StudentMapper.xml
    <resultMap type="com.gec.domain.Student" id="baseStudentResultMap">
    	<id column="id" property="studentId"/>
    	<result column="name" property="name"/>
    	<result column="sex" property="sex"/>
    	<result column="age" property="age"/>
    </resultMap> 
    <resultMap type="com.gec.domain.Student" id="queryStudentListResultMap" extends="baseStudentResultMap">
    	<association property="clazz" javaType="com.gec.domain.Clazz">
    		<id column="cls_id" property="clazzId"/>
    		<result column="clazz_name" property="clazzName"/>
    		<result column="code" property="code"/>
    	</association>
    </resultMap> 
    <select id="queryStudentList" resultMap="queryStudentListResultMap">
    	SELECT s.*,c.id AS cls_id,c.clazz_name,c.code
    	FROM tbl_student s,tbl_clazz c WHERE s.clazz_id=c.id;
    </select>
    <!-- 根据班级的id,获取学生列表 -->
    <select id="queryStudentByClazzId" resultMap="baseStudentResultMap">
      	select * from tbl_student where clazz_id=#{id};		
    </select>
    3、多对多
    商品表、订单表之间就是以多对多关联
    商品与订单的关系表
    描述多对多的数据表实现
    (1)商品pojo:
    Article.java
    public class Article implements Serializable {
    	private Integer articleId;
    	private String name;
    	private Double price;
    	private String remark;
    	private List<Order> orders;
    	省略setter/gettera方法
    }
    (2)商品表映射:
    ArticleMapper.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
    <mapper namespace="com.gec.mapper.ArticleMapper">
    	<resultMap type="article" id="baseArticleResultMap">
    		<id column="id" property="articleId"/>
    		<result column="NAME" property="name"/>
    		<result column="price" property="price"/>
    		<result column="remark" property="remark"/>
    	</resultMap>
    	<resultMap type="article" id="findArtcleByIdResultMap" extends="baseArticleResultMap">
    		<collection property="orders" javaType="ArrayList"
    			ofType="com.gec.domain.Article" column="id"
    			select="com.gec.mapper.OrderMapper.findOrderByArticleId"
    		>
    		</collection>
    	</resultMap>
    	<!-- 根据订单id查询商品 -->
    	<select id="findArtcleByOrderId" resultMap="baseArticleResultMap">
    		select * from tb_article  where id 
    		in (select article_id from tb_item where order_id=#{id}) 
    	</select>
    	<select id="findArtcleById" resultMap="findArtcleByIdResultMap">
    		select * from tb_article  where id=#{id}
    	</select>
    </mapper>
    (3)订单pojo:
    Order.java
    public class Order {
    	private Integer orderid;
    	private String code;
    	private Double total;
    	private List<Article> articles;
    	省略setter/getter方法
    }
    (4)订单表映射:
    OrderMapper.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
    <mapper namespace="com.gec.mapper.OrderMapper">
    	<resultMap type="order" id="baseOrderResultMap">
    		<id column="orderId" property="orderid"/>
    		<result column="CODE" property="code"/>
    		<result column="total" property="total"/>
    	</resultMap>
    	<resultMap type="order" id="queryOrderByUserIdRsultMap" extends="baseOrderResultMap">
    		<collection property="articles" javaType="ArrayList"
    			ofType="article" column="orderId"
    			select="com.gec.mapper.ArticleMapper.findArtcleByOrderId">
    		</collection>
    	</resultMap>
    	<!-- 根据商品id查询订单 -->
    	<select id="findOrderByArticleId" resultMap="baseOrderResultMap">
    		select * from tb_order  where id 
    		in (select order_id from tb_item where article_id=#{id}) 
    	</select>
    </mapper>

    展开全文
  • 文章目录案例描述1. 创建数据库person和card2. 创建bean对象3. 创建dao层映射层4. 创建连接数据库的属性文件db.properties(键值对形式)5....创建person和card,通过resultMap映射的一对一关联映射ass
  • java表关联一对多CRUD大致思路代码是怎样的,比如商品,商品标签表,mybatis框架实现,有详细一点的代码学习下更好
  • (1)实现一对一关系就先在实体类中添加一个你需要对应的对象作为实体类的字段 (2)同理,实现一对多关系就现在实体类中添加一个你需要对应集合作为实体类的字段 实体类这里就这样了 重点是到下面的Mapper.x
  • 1.一对查询:关键点在于collection标签 一对查询是指在查询一方对象的时候,同时将其所关联的多方对象也都查询出来。 一个班级有多个学生,一个学生只属于一个班级。 数据库student表里有个字段classno是外键,...
  • Mybatis关联查询一对一和一对多的实现

    万次阅读 多人点赞 2015-05-13 09:20:43
    本文主要讲了使用Mybatis实现关联查询,分为一对一和一对多两种情况,最后并对ResultMap进行一个简要说明。
  • Mybats 多表联合查询一对多操作

    千次阅读 2019-06-13 17:43:06
    首先实现一对一表联合查询,一个用户对应多张账户。 2、数据库 用户users 账户account 其中账户的uid为外键,指向的是用户的主键id 3、项目的目录 4、我们首先来看两个实体类,对应...
  • Mybatis一对一关联查询

    万次阅读 2016-09-18 10:30:23
    Mybatis一对一关联查询有两张,teacher和class,一个class班级对应一个teacher,一个teacher对应一个class需求是根据班级id 查询班级信息(带老师的信息)创建teacher和class:CREATE TABLE teacher ( t_id INT ...
  • MyBatis中一对一关联查询

    千次阅读 2016-12-19 14:36:18
    1、一对一关联查询的案例  1.1 需求  根据班级id查询班级信息(带老师信息)  1.2 创建和数据  创建一张教师和班级,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的...
  • Mybatis 对象嵌套关联查询一对

    千次阅读 2019-06-12 10:59:36
    因为这个联表查询重新创建个会比较好一些。如果直接在映射的mapper改的话,要改很多地方,其次就是容易把写的方法覆盖掉。但自己重新写个mapper的话,不会把自己的写的方法覆盖掉,自己想加...
  • 本文主要讲了使用Mybatis实现关联查询,分为一对一和一对多两种情况,最后并对ResultMap进行一个简要说明。
  • ssm 多表一对一查询

    千次阅读 2018-05-09 20:00:00
    转载自:...这里我们知道一个用户可以有多张订单,而一张订单只能属于一个用户,所以用户与订单间的关系是一对多而订单与用户间的关系是一对一。所以这里我们将订单...
  • 基于Mapper代理配置Mybatis多表查询一对一映射(三种方式) 一、mybatis多联查使用内连接 1、两联查中一对一关系对于POJO的体现(截图忽略了get,set方法)   2、编写对应的PaperMapper接口和在同目录下创建...
  • MyBatis系列之关联查询(一对一)

    千次阅读 2016-05-01 23:26:27
    我们以一个例子demo的形式,说明Mybatis的一对一关联查询 设计teachers classes设置外键 classes classes是课程,teachers是教师信息 这里是一对一的关联关系,当然实际中一般不是这样的...
  • association字面翻译为联合之意,Java项目开发中常遇到一对一关系的结果,例如,一个商品对应一个生产商,在查询结果中如果某两个对象是一对一关系一般使用association标签,用法有两种: 1,嵌套的resultMap,一次...
  • SSM 各种配置信息 就 不再赘述,之前篇写过。1 对应的 pojo - - - 1 字段 id、name List&lt;Two&gt;是2 查询返回来的结果集2 对应的 pojo ---- 2 字段 id、name、pid List&lt;Three&...
  • 映射方式: ...resultMap:在多表查询的时候,查询到多条数据,需要把数据封装到pojo中,再把pojo放到list集合中,这里用到了ofType属性; resultMap中用到的属性和标签标签://返回个list集合
  • mybatis关联查询(一对一与一对多)

    千次阅读 2019-05-30 22:16:08
    以前在写小demo的时候对于具有关联关系的对象,都是分别查的,但其实mybatis可以直接进行关联查询,今天就来详细讲一下用mybatis怎样进行一对一和一对多的关联查询. 一对一关系: 需求:假设有一个User类,一个Car类,...
  • resultMap元素(结果映射)【*****】级联关系【*****】4.1 一对一关联查询 (association) - 用javaType来指定对象类型4.2 一对多、多对多关联查询 (collection) - 用ofType来制定对象类型 映射器  
  • 一对一 商品中的classify_id关联商品分类中的id 返回商品列表数据时数据内包含商品分类信息 service /** * 获取商品列表 * * @param form */ @Override public Result goodsList(GoodsDto form) { ...
  • thinkphp5关联查询一对一跟多对多

    千次阅读 2019-01-19 16:49:23
    最近看了七月老师的视频,感觉数据库关系跟应用...那么,主题需要有图片跟基本信息,一个主题只有一个图片,一对一的关系  那么在主题模型中,需要定义关联关系 belongsTo('Image','主题图片外键','关联表主键(I...
  • if 标签 <!-- 演示动态sql-if标签的使用情景 --> <select id="getUserByWhere" parameterType="user" resultType="com.itheima.mybatis.pojo.User"> <!-- SELECT * FROM USER WHERE username LIKE...
  • demo.py(定义模型类,一对关联): # coding:utf-8 from flask import Flask from flask_sqlalchemy import SQLAlchemy # 导入 app = Flask(__name__) # 通过类对象加载配置。 (配置数据库) class Config...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 259,261
精华内容 103,704
关键字:

一对一表关联查询的标签