前言
在对数据库进行查询时,我们会遇到各种各样的查询需求,比如多表联结查询,这就需要了解一对一、一对多、多对多等概念。一对一顾名思义就是一个对象对应一个对象,比如一个班主任对应一个班级,这就是一对一,那么一对多可以理解为一个班级对应多个学生,在面向对象设计实体属性里就是班级类包含学生集合。下面用我的漫画查询作为例子来介绍这两种的关系。
例子
主要介绍的是一对多。在一部漫画中,通常关系都是这样的,一部漫画有多个章节,一个章节有多张图片,即是漫画:章节=1:n,漫画章节:章节图片=1:n。因此,在查询一部漫画所有内容时候我们可以通过先查漫画id获得漫画简介信息,然后通过漫画id获得章节列表,再根据每一个章节的id获得每一章的图片集合。下面分别使用了xml映射文件形式和注解形式实现这种关联查询方法。
首先要看看每个的实体类,不难发现都是一对多的关系
@Data public class Message { private Integer comicId; private String comicName; private List<ChapterModel> chapterList; }
@Data public class ChapterModel { private Integer chapterId; private String chapterName; private List<String> picList; }
|
映射文件形式
这种形式我使用了左外连接的sql写法,在两个连接关节都让左表作为主表来列出所有集合元素
<resultMap id="message" type="com.example.kbcomic.model.Message"> <result property="comicId" column="comic_id"></result> <result property="comicName" column="comic_name"></result> <collection property="chapterList" ofType="com.example.kbcomic.model.ChapterModel"> <result column="chapter_id" property="chapterId"></result> <result column="chapter_name" property="chapterName"></result> <collection property="picList" ofType="java.lang.String"> <result column="pic_url" property="picUrl"></result> </collection> </collection> </resultMap> <select id="queryMessageByComicId" resultMap="message" parameterType="java.lang.Integer"> select all_comic.comic_id, all_comic.comic_name, all_chapter.chapter_id, all_chapter.chapter_name, all_pic.pic_url from all_comic left join all_chapter on all_comic.comic_id=all_chapter.comic_id left join all_pic on all_chapter.chapter_id=all_pic.chapter_id where all_comic.comic_id=#{id} </select>
|
注解写法
这种方式其实是对数据库查了三次再拼接起来最后的集合
@Select("select comic_id,comic_name from all_comic where comic_id=#{id}") @Results({ @Result(column = "comic_id",property = "comicId"), @Result(column = "comic_name",property = "comicName"), @Result(property = "chapterList",column = "comic_id", many = @Many(select = "com.example.kbcomic.mapper.MessageMapper.queryChapterList")) }) Message queryMessage(@Param("id")Integer comicId); @Select("select chapter_id,chapter_name from all_chapter where comic_id=#{comic_id}") @Results({ @Result(column = "chapter_id",property = "chapterId"), @Result(column = "chapter_name",property = "chapterName"), @Result(property = "picList",column = "chapter_id", many = @Many(select = "com.example.kbcomic.mapper.MessageMapper.queryPicList")) }) List<ChapterModel>queryChapterList(@Param("comic_id")Integer id); @Select("select pic_url from all_pic where chapter_id=#{chapter_id}") List<String>queryPicList(@Param("chapter_id")Integer id);
|
这两种写法得到的结果都是一样的。
相关注释与标签的理解
在上面的例子中,主要有两个关键的注释或标签:@Many
和<collection>
。这两个分别在注解方式和xml映射文件中使用,意思是一样的。@Many
的select
属性指向的是合适类型集合的映射语句。如果在该映射语句中需要参数,则要通过同一级的@Result
标签中的column
属性指定并传递。而一对一的关系则需要用@One
和<association>
,其用法跟一对多一样。