mybatis ---- 级联查询 一对多 (集合映射)

2023-11-13

关联有嵌套查询和嵌套结果两种方式,本文是按照嵌套结果这种方式来说明的

上一章介绍了多对一的关系,用到了<association></association>,这是一个复杂类型的关联。我们选择一个示例来回顾下,比如:一个博客有一个用户,关联映射就工作于这种结果之上。首先看下,我们在本文中要用到的表结构字段:

博客
blog :  id  title  author_id 

作者
author:  id  username password email  bio favourite_section

文章
post :id  blog_id  author_id  created_on  section  subject  draft  body  

评论
comment : id   post_id  name  comment  

标签
T : id name 
我们把一个博客和一个用户关联在一起,就像:

   <select id="selectBlog" parameterType="int" resultMap="blogResult">
              select 
                  b.id as blog_id,
                  b.title as blog_title,
                  b.author_id as blog_author_id
                  a.id as author_id,
                  a.username as author_username,
                  a.password as author_passowrd,
                  a.email as auhtor_email,
                  a.bio as author_bio
               from  blog b left outer join author a on b.author_id=a.id
                    where b.id=#{id}
       </select>


注意这个联合查询,以及所有结果被唯一而清晰的名字而重命名。这使得映射非常简单。现在我们可以映射这个结果:

<resultMap id="blogResult" type="Blog">
     <id property="id" column="blog_id"/>
      <result property="title" column="blog_title"/>
      
      <!-- 和一个用户关联,Blog 类里面属性时author,关联的列是原先的blog.author_id-->
      <association property="author"  column="blog_author_id" javaType="Author"  resultMap="authorResult"/>
</resultMap>

<resultMap id="authorResult" type="Author">
          <id property="id" column="author_id"/>
          <result property="username" column="author_username"/>
          <result property="password" column="author_password"/>
          <result property="email" column="author_email"/>
          <result property="bio" column="author_bio"/>
</resultMap>

在上面的例子中,你可以看到博客的作者关联authorResult 结果映射来加载作者实例。  上面的实例中,用了外部的结果映射元素来映射关联。这使得Author结果映射可以重用。然而,你不需要重用它的话,或者你仅仅引用你所有的结果映射到一个单独描述的结果映射中。你可以嵌套结果映射。这里给出使用这种方式的相同示例:

<resultMap id="blogResult" type="Blog">
     <id property="id" column="blog_id"/>
      <result property="title" column="blog_title"/>
      
      <!-- 和一个用户关联,Blog 类里面属性时author,关联的列是原先的blog.author_id-->
      <association property="author"  column="blog_author_id" javaType="Author" >
	          <id property="id" column="author_id"/>
	          <result property="username" column="author_username"/>
	          <result property="password" column="author_password"/>
	          <result property="email" column="author_email"/>
	          <result property="bio" column="author_bio"/>
      </association>
</resultMap>

上面你已经看到了如何处理有一个类型的关联.但是“有很多个”是怎样的呢?,也就是集合类型,本文的主要工作是来说这个的


集合

相对于关联来说,集合映射多了一个属性”ofType“.这个属性用来区分 JavaBean(或字段)属性类型集合包含的类型来说是很重要的. ,ofType用来表示集合包含类型。
     <collection property="posts"  ofType="Post">
            <id property="id" column="post_id"/>
            <result property="subject" column="post_subject"/>
            <result property="body" column="post_body"/>
      </collection>
集合元素的作用和关联几乎是相同的。我们来继续上面的示例,一个博客只有一个作者。但是博客有很多文章,在博客类中,这可以由下面的写法来表示:
private List<Post> posts; 
这一次联合博客表和文章表(一个blog_id可以对应很多的文章)SQL如下:
<select id="selectBlog" parameterType="int" resultMap="blogResult">
         select 
             b.id as blog_id ,
             b.title as blog_title,
             b.author_id as blog_author_id,
             p.id as post_id,
             p.subject as post_subject,
             p.body as post_body
           from blog b
               left outer join  post p on b.id=p.blog_id
               where b.id=#{id}  
</select>
现在用“文章映射集合”来映射 “博客“,可以简单写为:
<resultMap id="blogResult" type="Blog">
    <id property="id" column="blog_id"/>
    <result property="title" column="blog_title"/>
    <collection property="posts" ofType="Post">
        <id property="id" column="post_id"/>
        <result property="subject" column="post_subject"/>
        <result property="body" column="post_body"/>
    </collection>
</resultMap>
高级关联和集合映射还有很多要琢磨的地方。就让面介绍的集合映射,稍微的整理下(一个博客下面,有很多文章).
首先创建下,需要用到的表格,以及向其中插入一些数据. 
create table author(id int (11) not null auto_increment,
                    username varchar(20) not null,
                    password varchar(20) not null, 
                    email varchar(20) not null,
                    bio varchar(20) not null,
                    favourite_section varchar(20) not null,
                     primary key(id)
                  )ENGINE=InnoDB DEFAULT CHARSET=utf8;
                  

insert into author(id,username,password,email,bio,favourite_section) 
values(1001,'林枫','123456','824156593@qq.com','合肥的小男孩','旅游');

        
        
create table blog (id int (11) not null auto_increment,
                    title varchar(20) not null,
                     author_id int(11) not null,
                      primary key(id))
                     ENGINE=InnoDB DEFAULT CHARSET=utf8;  
 
 insert into blog(id,title,author_id) values(1,'小说博客',1001);                    
                     
create table post(id int (11) not null auto_increment,
                  blog_id int(11) not null,
                  author_id int(11) not null,
                  created_on date not null,
                  section varchar(20) not null,
                  subject varchar(20) not null,
                  draft varchar(20) not null,
                  body varchar(20) not null,
                   primary key(id)
                    )ENGINE=InnoDB DEFAULT CHARSET=utf8;       
                    
                    
insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)
values(1,1,1001,now(),'旅游','玄幻','草稿','绝世武神');  
  
insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)
values(2,1,1001,now(),'旅游','玄幻','草稿','大主宰');

insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)
values(3,1,1001,now(),'旅游','玄幻','草稿','灵域');     

在贴JAVA代码之前,先看下目录结构吧:
作者类 Author.java
package com.mybatis.model;
/**
 * 作者类
 * @author Administrator
 *
 */
public class Author {
	
	private int id;
	private String username;
	private String password;
	private String email;
	private String bio; //个人资料
	private String favourite_section; //最喜欢的。。
	
	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;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getBio() {
		return bio;
	}
	public void setBio(String bio) {
		this.bio = bio;
	}
	public String getFavourite_section() {
		return favourite_section;
	}
	public void setFavourite_section(String favouriteSection) {
		favourite_section = favouriteSection;
	}
	
}
Blog.java
package com.mybatis.model;

import java.util.List;

/**
 * 博客类
 * @author Administrator
 *
 */
public class Blog {
	private int id;
	private String title;
	private Author author;
	private List<Post> posts; //博客类有很多文章, 与post表中的blog_id对应
	
	public List<Post> getPosts() {
		return posts;
	}
	public void setPosts(List<Post> posts) {
		this.posts = posts;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public Author getAuthor() {
		return author;
	}
	public void setAuthor(Author author) {
		this.author = author;
	}
	
}

文章类Post.,java
package com.mybatis.model;

import java.util.Date;

/**
 * 文章类
 * @author Administrator
 *
 */
public class Post {
	private int id;
	private int blog_id;
	private int author_id;
	private Date created_on;
	private String section;
	private String subject;
	private String draft;
	private String body;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getBlog_id() {
		return blog_id;
	}
	public void setBlog_id(int blogId) {
		blog_id = blogId;
	}
	public int getAuthor_id() {
		return author_id;
	}
	public void setAuthor_id(int authorId) {
		author_id = authorId;
	}
	public Date getCreated_on() {
		return created_on;
	}
	public void setCreated_on(Date createdOn) {
		created_on = createdOn;
	}
	public String getSection() {
		return section;
	}
	public void setSection(String section) {
		this.section = section;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getDraft() {
		return draft;
	}
	public void setDraft(String draft) {
		this.draft = draft;
	}
	public String getBody() {
		return body;
	}
	public void setBody(String body) {
		this.body = body;
	}
	
}
总配置文件
<?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>
  <typeAliases>
    <!-- 给实体类去一个别名  -->
        <typeAlias type="com.mybatis.model.Blog" alias="Blog"/> 
        <typeAlias type="com.mybatis.model.Post" alias="Post"/>
  </typeAliases>
  
  <!-- 数据源配置,这里用MySQL数据库 -->
  <environments default="development">
     <environment id="development">
         <transactionManager type="JDBC"/>
         <dataSource type="POOLED">
               <property name="driver" value="com.mysql.jdbc.Driver"/>
               <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
               <property name="username" value="root"/>
               <property name="password" value="123456"/>
         </dataSource>
     </environment>
  </environments>
  
  <mappers>
        <mapper resource="com/mybatis/model/Blog.xml"/>
  </mappers>
  
</configuration>

Blog.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.mybatis.dao.IBlogDao">

<!-- 用文章映射集合来映射博客 -->
<resultMap id="blogResult" type="Blog">
    <id property="id" column="blog_id"/>
    <result property="title" column="blog_title"/>
    
    <!--文章集合 -->
    <collection property="posts" ofType="Post">
        <id property="id" column="post_id"/>
        <result property="subject" column="post_subject"/>
        <result property="body" column="post_body"/>
    </collection>
</resultMap>

<select id="selectBlog" parameterType="int" resultMap="blogResult">
         select 
             b.id as blog_id ,
             b.title as blog_title,
             b.author_id as blog_author_id,
             p.id as post_id,
             p.subject as post_subject,
             p.body as post_body
           from blog b
               left outer join  post p on b.id=p.blog_id
               where b.id=#{id}  
</select>
</mapper>

测试类Test.java
package com.mybatis.test;

import java.io.IOException;
import java.util.List;

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 com.mybatis.dao.IBlogDao;
import com.mybatis.model.Blog;
import com.mybatis.model.Post;

public class Test {
	
	/***
	 * 获得MyBatis SqlSessionFactory
	 * SqlSessionFactory 负责创建SqlSession ,一旦创建成功,就可以用SqlSession实例来执行映射语句
	 * ,commit,rollback,close等方法
	 * @return
	 */
	private static SqlSessionFactory getSessionFactory(){
		SqlSessionFactory sessionFactory=null;
		String resource="configuration.xml";
		 try {
			sessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader(resource));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return sessionFactory;
	}
	
	/**
	 * main 方法
	 * @param args
	 */
	public static void main(String[] args) {
		
          SqlSession session=getSessionFactory().openSession();
     try {
    	 IBlogDao blogDao=session.getMapper(IBlogDao.class);
    	 Blog blog=blogDao.selectBlog(1);
         List<Post> postList=blog.getPosts();
         for(Post post:postList){
        	 System.out.println(post.getBody());
         }
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			session.close();
		}
	}
}
运行后结果如下:
DEBUG [com.mybatis.dao.IBlogDao.selectBlog] - ooo Using Connection [com.mysql.jdbc.Connection@e00ed0]
DEBUG [com.mybatis.dao.IBlogDao.selectBlog] - ==>  Preparing: select b.id as blog_id , b.title as blog_title, b.author_id as blog_author_id, p.id as post_id, p.subject as post_subject, p.body as post_body from blog b left outer join post p on b.id=p.blog_id where b.id=? 
DEBUG [com.mybatis.dao.IBlogDao.selectBlog] - ==> Parameters: 1(Integer)
绝世武神
大主宰
灵域


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mybatis ---- 级联查询 一对多 (集合映射) 的相关文章

随机推荐

  • .exe已停止工作_R027---Uipath调用python程序的exe

    一 缘起 看到不少朋友问Uipath调用python的方法 这里说一个方法 调用python程序编译后的exe 其他开发语言的程序也可以这么调用 由于调用的是exe文件 所以 其实没有用到UiPath Python Activities 用
  • Ubuntu常用命令大全

    转自 https www jb51 net os Ubuntu 56362 html 一 文件 文件夹管理 ls 列出当前目录文件 不包括隐含文件 ls a 列出当前目录文件 包括隐含文件 ls l 列出当前目录下文件的详细信息 cd 回当
  • 层次分析法的理解

    AHP 层次分析法 层次分析法的特点 基本概念 重要性表 判断矩阵 为什么要引入判断矩阵呢 判断矩阵的特点 一致矩阵 为什么要定义一致矩阵呢 一致矩阵的特点 一致矩阵的引理 一致性检验的步骤 判断矩阵计算权重 算术平均法求权重 几何平均法
  • 一个很好用的小控件----给所有view右上角添加数字(类似未读消息之类的)

    下面这种效果 Badge 用法很简但 见下面的demo Created by Fangchao on 2015 2 25 EActivity R layout activity usercenter public class UserCen
  • 软件测试及原则

    软件测试 英语 software testing 描述一种用来促进鉴定软件的正确性 完整性 安全性和质量的过程 换句话说 软件测试是一种实际输出与预期输出间的审核或者比较过程 软件测试的经典定义是 在规定的条件下对程序进行操作 以发现程序错
  • 几种压缩算法

    一 行程长度压缩 原理是将一扫描行中的颜色值相同的相邻像素用一个计数值和那些像素的颜色值来代替 例如 aaabccccccddeee 则可用3a1b6c2d3e来代替 对于拥有大面积 相同颜色区域的图像 用RLE压缩方法非常有效 由RLE原
  • Java多线程:线程8锁案例分析

    线程8锁案例分析 通过分析代码 推测打印结果 并运行代码进行验证 1 两个线程调用同一个对象的两个同步方法 被synchronized修饰的方法 锁的对象是方法的调用者 因为两个方法的调用者是同一个 所以两个方法用的是同一个锁 先调用方法的
  • 编译filament

    从github上下载github 每次都被中断 于是灵机一动 从码云上下载1 8下载 果然速度快 先cmake 发现需要python 把enable java去掉 编译后试试 hellopbr
  • nginx系统学习5--常用配置4--防盗链配置

    6 4 防盗链配置 6 4 1 操作 01 配置 server listen 7000 server name www test com www test1 com root html www test location index tes
  • PTA数组2

    目录 1 方阵对角线元素求和及计数 2 使用选择法升序 3 输入10个正整数到a数组中 对a 10 数组中的素数升序排序 4 对a 10 数组中的素数排序 1 方阵对角线元素求和及计数 对输入的一个N N的方阵 求其两条对角线上的元素之和及
  • Excel根据身份证号提取省份

    身份证号码各位的含义 1 2位省 自治区 直辖市代码 3 4位地级市 盟 自治州代码 5 6位县 县级市 区代码 7 14位出生年月日 比如19670401代表1967年4月1日 15 17位为顺序号 其中17位 倒数第二位 男为单数 女为
  • 关于多线程的爬取心得和用法

    最近爬取一些学习上所要用到的东西 因为要搞得东西比较多 写的爬取的速度大大下降 于是我就尝试提升以下程序爬取的速度 正好学过多线程 灵机一动就搞了个多线程的程序爬取 此次没有啥好说的 有啥不懂请看注释 import queue import
  • (Java 功能篇) Java Proxool

    本文题目没有强调的是Java应用 不是Java Web应用 原因是从网上找有关Proxool的例子 全是一个摸样 都是将讲解Java Web中的应用 真没劲 难道Proxool离开了web就不能用了 不信你可以google一把看看 在阅读了
  • 定时器之编码器模式

    1 什么是编码器 编码器 encoder 是将信号或数据进行编制 转换为可用以通讯 传输和存储的信号形式的设备 编码器把角位移或直线位移转换成电信号 前者称为码盘 后者称为码尺 2 分类 按照读出方式编码器可以分为接触式和非接触式两种 按照
  • [转]IDEA中使用Debug

    一 Debug开篇 首先看下IDEA中Debug模式下的界面 如下是在IDEA中启动Debug模式 进入断点后的界面 我这里是Windows 可能和Mac的图标等会有些不一样 就简单说下图中标注的8个地方 以Debug模式启动服务 左边的一
  • VS环境下,关于“找不到 **.dll,无法执行代码,重新安装程序可能会解决此问题。”的四种解决方案

    dll 是动态链接库文件 里面存储着函数和数据 lib是静态数据连接库文件 存储着函数名和文件位置 也就是说在执行程序时 exe文件可通过lib文件找到dll文件 并执行在程序中调用的函数 Windows在查找dll文件会按照以下几种方式顺
  • 被动遥感和主动遥感的概念辨析

    主动遥感 主动遥感 又称有源遥感 有时也称遥测 指从遥感平台上的人工辐射源 向目标物发射一定形式的电磁波 再由传感器接收和记录其反射波的遥感系统 其主要优点是不依赖太阳辐射 可以昼夜工作 而且可以根据探测目的的不同 主动选择电磁波的波长和发
  • CSS > Flex 布局中的放大和收缩计算

    原文 https dev opera com articles flexbox basics 译者注 本文仅简单翻译下原文中关于如何计算 flex 属性的值的部分 其他有关 Flex 布局的知识本文不作探讨 2015 12 5更新 关于 f
  • pixi.js 导出部分区域裁剪图片

    方案 先通过api到出image对象 在通过canvas绘制图片 在导出数据 代码 const x y this app stage getBounds 超出的x y const stageImage this app renderer p
  • mybatis ---- 级联查询 一对多 (集合映射)

    关联有嵌套查询和嵌套结果两种方式 本文是按照嵌套结果这种方式来说明的 上一章介绍了多对一的关系 用到了