Mybatis实现高级映射一对一、一对多查询
终于把论文写得差不多了,系统也不急着完成,可以抽出点时间来完成这个系列的博客了。在写本博客之前我是惶恐不安的,高级映射一贯是持久层框架里的重中之重,小到自己开发小系统,大到企业级开发,表的存在从来就不独立的。复杂交错的表之间的联系有时的确让后台开发人员头疼,而作为一个框架,要做的事就是把这种复杂程度降到最低。既然如此,我们就赶快进入正文吧。
先说一对一吧,前几篇博文里用到了User类,今天我们再加上一个Orders订单类

一个订单只能由一个用户创建,所以根据订单查找用户是一对一的查找,所以当我想查出订单关联用户的所有记录怎么查呢?
我们知道这个查询时不用输入参数的,所以在select里面是不用输入parameterType的,由此可知查询关键就在resultType了,的确,但是今天resultType有时会不够用,当然这都是后话了,在一对一查询里面resultType完全是够用的,所以先看看这个怎么用吧
先分析一波,我们之前的所有的输出都有相会映射成相应的类,而我们现在没有一个既包含User属性又包含Orders的类怎么办呢?
没错,就是新建一个满足以上条件的类,在这里有一个小技巧,我们大多时候不需要关联表里的所有属性,比如在这里我们只要user类的用户名和地址两个属性时,可以创建一个Orders类的扩展类,在该扩展类里添加属性username和address,就像下面

解决了映射类,接下来就是xml文件了
先把sql语句贴上来
SELECT
orders.*, user.username, user.address
FROM
orders,
user
WHERE
orders.user_id = user.id;
这个sql语句很简单我就不多说了,有了这个mapper.xml就简单了
<select id="findOrderCustom" resultType="com.mybatis.pojo.OrderCustom">
SELECT
orders.*, user.username, user.address
FROM
orders,
user
WHERE
orders.user_id = user.id;
</select>
然后就是遵循规范把mapper接口中的方法写了
//查询Orders关联User使用resultType
public List<OrderCustom> findOrderCustom();
最后是测试代码
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//创建会话会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindOrderCustom() throws Exception {
//创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建mapper代理对象
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
List<OrderCustom> list=userMapper.findOrderCustom();
//调用代理对象的方法,打印结果
System.out.println(list.size());
sqlSession.close();
}
}
大功告成,这个测试代码我已经测试过了没有问题,所以如果有跟初学者想拿着博主的代码运行一遍也是没有问题的。
其实从最开始学到现在,博主一直有一个疑问,为了实现映射一直以来表和类中属性的命名都要保持一致。但是我们的java类规范命名都是用驼峰命名法,而数据库中属性命名大多采用下划线,这样保持一致不得不改变一方的命名规则,有没有什么方法可以两全呢?
答案就是resultMap,跟resultType直接进行类的映射不同,resultMap讲究的是属性的映射。为了举例我再引进一个类,商品类Goods

表结构是这样的

接下来要做的事就是使用resultMap从表中查出所有的数据
在使用resultMap之前要先定义它,怎么定义呢,看代码
<!-- 定义resultMap -->
<resultMap type="com.mybatis.pojo.Goods" id="goodsResultMap">
<id column="id" property="id"/>
<result column="goods_name" property="goodsName"/>
<result column="goods_price" property="goodsPrice"/>
</resultMap>
主键用的是id,普通属性统一使用result。其中column和property分别代表在表和类中的属性名。resultMap的id是为了让下面的select语句引用的,接下来就给出select语句
<!-- 用resultMap查询goods信息 -->
<select id="findGoodsResultMap" resultMap="goodsResultMap">
select * from goods
</select>
整个xml的工作就算完成了,老规矩,下面给出mapper接口中的方法和测试代码(注意所有的测试都要加上@before的内容,我这里就懒得再写了)
//查询goods使用resultMap
public List<Goods> findGoodsResultMap();
//测试查询goods使用resultMap
@Test
public void testFindGoodsResultMap() throws Exception {
//创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建mapper代理对象
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
List<Goods> list=userMapper.findGoodsResultMap();
//调用代理对象的方法,打印结果
System.out.println(list.size());
sqlSession.close();
}
写到这里,是不是有人想叫博主用resultMap的方法来写一写之前一对一的查询呢,放心吧,我后面也会讲到的。
首先看需求,如果我想列出所有用户的所有订单,但是用户信息又不能重复该怎么办,这个时候resultType就不够用了,因为需求是用户信息不能重复所以订单类要以list的方式存在
用户类中如下所示

而我们的user表能否直接与上面的类对应呢,显然是不行的,既然不行的话resultMap就要上场了,之前就说过resultMap是细化到属性的对应的,我们完全可以将User类中的list中的对象细化到单独对应orders表,这样问题就解决了啊,那resultMap要怎么定义呢
首先把除去list的属性映射完(懒得麻烦就只写了id,username,address三个属性),写完就是下面这个样子
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="address" property="address"/>
</resultMap>
千万要记住我们的主表是user表,所以这里的type是User类
在resultMap里有一个属性collection,这个属性是专门为list准备的,让我们来看看加上这个会是什么样子的
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="address" property="address"/>
<collection property="orderList" ofType="com.mybatis.pojo.Orders">
<id column="id" property="id"/>
<result column="user_id" property="user_id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
</collection>
</resultMap>
在collection中的property对应类中的属性名,ofType对应类中的list中的对象类型,在这里就是Orders类了,剩下的东西就和之前的配置完全一样了,无非是将orders类中的属性名和表中的属性名对应了。
接下来就是select语句了
<!-- 查询用户关联订单使用resultMap -->
<select id="findUserAndOrdersResultMap" resultMap="userAndOrdersResultMap">
SELECT
user.id, user.username, user.address, orders.*
FROM
orders,
user
WHERE
user.id = orders.user_id;
</select>
是不是sql语句发现和之前写的好像是一样的,啊哈哈,我也是写完才发现的,需求是随便编的。。。
下面是mapper接口中的方法和测试代码(注意所有的测试都要加上@before的内容,我这里就懒得再写了)
//查询User关联Orders使用resultMap
public List<User> findUserAndOrdersResultMap();
//测试查询User关联Orders使用resultMap
@Test
public void testFindUserAndOrdersResultMap() throws Exception {
//创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建mapper代理对象
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
List<User> list=userMapper.findUserAndOrdersResultMap();
//调用代理对象的方法,打印结果
System.out.println(list.size());
sqlSession.close();
}

我的数据库orders表中有三条记录,两条是同一个用户创建的,所以输出结果应该是2,没问题
最后啰嗦一点
如果需求变成订单再关联商品信息该怎么写呢,我们知道订单和商品也是一对一的,即一个订单里面只能有一个该商品的记录(注意,这里的一个指的不是一件,如果用户买了多件该商品最后也会变成一个商品记录,变的只是数量而已),相当于在Orders类中增加一个Goods类作为属性,这个时候该怎么写呢,Mybatis提供了一个叫做association的属性用于关联类,相当于在collection里加上一个association,这个时候,xml文件会变成这样
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="address" property="address"/>
<collection property="orderList" ofType="com.mybatis.pojo.Orders">
<id column="id" property="id"/>
<result column="user_id" property="user_id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/> <association property="goods" javaType="com.mybatis.pojo.Goods">
<id column="id" property="id"/>
<result column="goods_name" property="goodsName"/>
<result column="goods_price" property="goodsPrice"/>
</association> </collection>
</resultMap>
这个博主就不去测试了,反正套路都是一样的
有了association,之前那个订单关联用户的查询也就迎刃而解了,只需在Orders类中加一个用户类的属性紧接着配一个association就OK了。
终于写完了,我长舒了一口气,花了大半个下午的时间呢,后面还会写多对多查询,整合spring框架的内容等等。。。
最后最后说一点,这些知识我也是在短期内学完的,算是现学现卖,如果哪位大神“随意”看了一眼发现了错误或者有更好的见解还请不吝赐教啊
Mybatis实现高级映射一对一、一对多查询的更多相关文章
- 19_高级映射:一对多查询(使用resultMap)
[需求] 查询订单以及订单明细的信息. 确定主查询表:订单表orders 确定关联查询表:订单明细表 orderdetail 在一对一查询的基础上添加订单明细表关联即可. [分析] 使用resultM ...
- mybatis入门基础(六)----高级映射(一对一,一对多,多对多)
一:订单商品数据模型 1.数据库执行脚本 创建数据库表代码: CREATE TABLE items ( id INT NOT NULL AUTO_INCREMENT, itemsname ) NOT ...
- Mybatis(四) 高级映射,一对一,一对多,多对多映射
天气甚好,怎能不学习? 一.单向和双向 包括一对一,一对多,多对多这三种情况,但是每一种又分为单向和双向,在hibernate中我们就详细解析过这单向和双向是啥意思,在这里,在重复一遍,就拿一对多这种 ...
- 【mybatis深度历险系列】mybatis中的高级映射一对一、一对多、多对多
学习hibernate的时候,小编已经接触多各种映射,mybatis中映射有到底是如何运转的,今天这篇博文,小编主要来简单的介绍一下mybatis中的高级映射,包括一对一.一对多.多对多,希望多有需要 ...
- Mybatis学习总结(六)——高级映射(一对一,一对多,多对多)
一.订单商品数据模型 1.数据库执行脚本 创建数据库表代码: /*Table structure for table `t_user` */ CREATE TABLE t_user ( id INT ...
- mybatis入门基础----高级映射(一对一,一对多,多对多)
阅读目录 一:订单商品数据模型 二.一对一查询 三.一对多查询 四.多对多查询 回到顶部 一:订单商品数据模型 1.数据库执行脚本 创建数据库表代码: CREATE TABLE items ( id ...
- mybatis3.2.7应用_高级映射(一对一、一对多、多对多)
1. 一对一查询 需求:查询订单信息,关联查询创建订单的用户信息 1.1 使用resultType实现 1.1.1 sql语句 确定查询的主表:订单表 确定查询的关联表:用户表 ...
- MyBatis学习--高级映射
简介 前面说过了简单的数据库查询和管理查询,在开发需求中有一些一对一.一对多和多对多的需求开发,如在开发购物车的时候,订单和用户是一对一,用户和订单是一对多,用户和商品是多对多.这些在Hibernat ...
- Mybatis学习记录(六)----Mybatis的高级映射
1.一对多查询 1.1 需求 查询订单及订单明细的信息. 1.2 sql语句 确定主查询表:订单表 确定关联查询表:订单明细表 在一对一查询基础上添加订单明细表关联即可. SELECT orders. ...
随机推荐
- scrapy爬虫学习系列四:portia的学习入门
系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备: http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...
- Android总结篇系列:Activity启动模式(lauchMode)
本来想针对Activity中的启动模式写篇文章的,后来网上发现有人已经总结的相当好了,在此直接引用过来,并加上自己的一些理解,在此感谢原作者. 文章地址: http://blog.csdn.net/l ...
- Linux svn checkout时候总报设备上没有空间
详细报错信息:svn: 不能打开文件“weibosearch2.0.0/.svn/lock”: 设备上没有空间 但是df -h查看磁盘[root@picdata-1-2 data]# df -h文件系 ...
- Docker最全教程——从理论到实战(八)
在本系列教程中,笔者希望将必要的知识点围绕理论.流程(工作流程).方法.实践来进行讲解,而不是单纯的为讲解知识点而进行讲解.也就是说,笔者希望能够让大家将理论.知识.思想和指导应用到工作的实际场景和实 ...
- 痞子衡嵌入式:ARM Cortex-M文件那些事(5)- 映射文件(.map)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的map文件. 第四节课里,痞子衡给大家介绍了第一种output文件-relocatable文件,本文继续给大家讲projec ...
- 痞子衡嵌入式:语音处理工具Jays-PySPEECH诞生记(6)- 文语合成实现(pyttsx3, eSpeak1.48.04)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是语音处理工具Jays-PySPEECH诞生之文语合成实现. 文语合成是Jays-PySPEECH的核心功能,Jays-PySPEECH借 ...
- 第57章 GrantValidationResult - Identity Server 4 中文文档(v1.0.0)
该GrantValidationResult类模型补助确认为扩展授权和资源所有者密码授权的结果. 最常见的用法是使用身份验证(成功用例): context.Result = new GrantVali ...
- 如何使用在三星840 SSD硬件加密下使用Bitlocker
我的笔记本存放到比较重要的资料,需要加密,想到我的三星EVO 850 SSD支持三种加密模式,于是想使用全盘加密模式.但是找了半天没找到一点合适的中文资料,于是怒而翻译一下加密全盘加密的Bitlock ...
- [Go] go get获取官方库被墙解决
1.直接在github上clone对应的代码 , 地址为: https://github.com/golang/xxxxxxx.git xxxxxxx为所缺的库名 , 比如net库 text库 h ...
- arcgis for js学习之Graphic类
arcgis for js学习之Graphic类 <title>Graphic类</title> <meta charset="utf-8" /> ...