mybatis关联
web项目开发中目前很多企业都是在SSM框架基础上开发。其中的M指的的mybatis(ibatis).mybatis里指的一说的是规避了传统的jdbc等的繁琐。在mybatis中我们可以只用关注sql本身。而不用太在意之个执行过程。大大简化了我们平时的开发。mybatis深究的话会有很多要说的。今天我们只来看看mybatis中提供了映射中的关联标签。
数据准备
数据结构
下表stage_order中的stage_list是有stage表中ID组成的一个字符串,之间由逗号相隔。比如stage_list=1,2,3表示该stage_order中关联着ID为1或2或3的stage。我们得分别取查询stageID=1或2或3的stage进行实体映射展示。下一节我们看看实体的构造

实体准备
基本实体(对应stage_order单表)
- 在下面的实体中出现的注解我们不需要在意,这是swagger框架的注解,在本章节中不需要理解。换句话说我们可以吧注解删掉。不会影响我们的功能的。
@ApiModel(description = "阶段顺序表")
@Table(name = "STAGE_ORDER")
public class StageOrder {
@Id
@ApiModelProperty("阶段顺序ID")
@NotNull(message = "阶段顺序ID不可为空(NULL)")
private Long stageOrderId;
@ApiModelProperty("路口编号")
@NotNull(message = "路口编号不可为空(NULL)")
private Long intersectionId;
@ApiModelProperty("相序名称")
@NotBlank(message = "相序名称不可为空白")
@ByteLength(max = 30, message = "相序名称长度不能超过{max}")
private String orderName;
@ApiModelProperty("阶段列表")
@NotBlank(message = "阶段列表不可为空白")
@ByteLength(max = 200, message = "阶段列表长度不能超过{max}")
private String stageList;
public Long getStageOrderId() {
return stageOrderId;
}
public void setStageOrderId(Long stageOrderId) {
this.stageOrderId = stageOrderId;
}
public Long getIntersectionId() {
return intersectionId;
}
public void setIntersectionId(Long intersectionId) {
this.intersectionId = intersectionId;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName == null ? null : orderName.trim();
}
public String getStageList() {
return stageList;
}
public void setStageList(String stageList) {
this.stageList = stageList == null ? null : stageList.trim();
}
}
扩展实体
public class StageOrderDto extends StageOrder {
/**
* 相位列表
*/
private List<Stage> stageInfoList;
public List<Stage> getStageInfoList() {
return stageInfoList;
}
public void setStageInfoList(List<Stage> stageInfoList) {
this.stageInfoList = stageInfoList;
}
}
基本映射
一对一
- 有了上面的实体和对应的Table,那么我们如何在mybatis中将Table和实体关联呢。看如下在mapper.xml中的配置
<resultMap id="BaseResultMap" type="com.jsits.xk.dto.StageOrderDto">
<id column="STAGE_ORDER_ID" jdbcType="NUMERIC" property="stageOrderId"/>
<result column="INTERSECTION_ID" jdbcType="NUMERIC" property="intersectionId"/>
<result column="ORDER_NAME" jdbcType="VARCHAR" property="orderName"/>
<result column="STAGE_LIST" jdbcType="VARCHAR" property="stageList"/>
<association column="STAGE_LIST" property="stageInfoList" select="selectStageInfos"/>
</resultMap>
但是我们会发现resultMap中stageInfoList这个在跟数据库怎么对应呢?还有association是什么?assocaition中select又是什么?为什么assocaition中的column和上面一样?
我想对于刚接触的朋友来说心里一定会有这些疑问。上面已经说了resultmap是用来衔接实体去数据库表的桥梁。resultMap中ID属性就是一个唯一性的作用。一般只需要在当前xml中唯一就行了。因为在每个xml中有
namespace,来确定当前的mapper.xml的唯一性。

- resultMap字标签id 和result都是用来映射单列值到type对应的实体或者map中属性。在使用上ID是对应数据库中主键使用的。数据库中会有联合主键,在resultMap中就用两个ID标签对应就行了。还有一点ID也是用来做唯一标识的。当和其他对象进行比较的时候这个时候ID就有作用了。这里和数据库一样主键就是代表一条数据。这里也是同样的作用。在mybatis中有缓存机制。就是通过这个ID实现的。比如mybatis这个时候需要缓存这个对象。则以ID为key ,对象的json化为值存储到缓存中。
一对多
这里一对多就用到了上面的BaseResultMap这个resultMap了。上面我们的讲的ID和result就是我们平时简单单表查询中的一对一关系处理。但是association就是用来关联查询的。association中文翻译就是联想的意思。在mybatis中association的作用就是在查询到STAGE_LIST这个字段的时候默认会将STAGE_LIST的值传到selectStageInfos这个查询语句中查询。传递进去是按照上面的写法我们不能用#{stage_list}取,得通过#{id}获取。这里是默认的必须用#{id}.但是一个健全的框架不会这么死板的。下面我们在介绍如何动态传递。
association严格上来说应该是用于selectStageInfos查询获取的也是一个基本类型数据。但是在我们上面的需求描述中我们知道STAGE_LIST,对应到stage表中其实回事多条数据。所以我们在StageOrderDto中stageInfoList也是用list集合来承载的。这个时候用association不会出错。mybatis底层却不同,底层实际上是转换成了collection标签来实现的。应为collection对应的是集合的映射处理。所以追求完美的程序员在级联查询是如果级联出的是集合就用collection标签。但是两种情况用association都是可以的。
查询应用
- 说了这么多,下面我们通过两个查询看看查询的实现代码
<select id="selectStageOrderDtoListByIntersectionId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from stage_order
where INTERSECTION_ID=#{intersectionId}
</select>
<select id="selectStageInfos" parameterType="java.lang.String" resultType="com.jsits.xk.model.Stage">
select
<include refid="Stage_Column_List"/>
from stage
where stage_id in (#{id})
</select>
- 当我们调用selectStageOrderDtoListByIntersectionId通过intersectionId查询到数据的时候,会在通过查询到的STAGE_LIST作为条件调用selectStageInfos这个查询语句的。在selectStageInfos中的#{id}就是selectStageOrderDtoListByIntersectionId查询到的STAGE_LIST。
复杂映射
- 但是我们平时企业开发中光这样的查询有时候并不能满足我们的需求。常见复杂的查询有: 多重级联和联合主键查询
多重映射
- 多重查询说白了就是多用几次级联(association或collection),对就是这个简单。这个可能有的人没有过甚至没想过。下面贴段实际的代码。因为下面代码在联合主键章节也需要用到。
<sql id="Program_Column_List">
PHASE_LIST,PROGRAM_ID,PROGRAM_NAME,INTERSECTION_ID,STAGE_ID,STAGE_NAME,STAGE_SEQ,GREEN,RED_YELLOW,YELLOW,ALL_RED,MIN_GREEN,MAX_GREEN
</sql>
<resultMap id="weekProgramResultMap" type="com.jsits.xk.dto.WeekPlanProgramDto">
<result column="PLAN_ID" property="planId" />
<result column="PLAN_NAME" property="planName" />
<association column="{intersectionId=INTERSECTION_ID,dayPlanNo=PLAN_ID}" property="dayPlanList" select="selectDayPlanInfosByPlanNo"/>
</resultMap>
<resultMap id="dayPlanResultMap" type="com.jsits.xk.dto.DayPlanAndProgramListDto">
<result property="timeDuration" column="time_duration" />
<result property="programId" column="program_id" />
<result property="stageOrderId" column="stage_order_id" />
<result property="dayPlanId" column="day_plan_id" />
<result property="phaseList" column="phase_list" />
<result property="programName" column="program_name" />
<result property="stageOrderName" column="order_name" />
<result property="controlModeId" column="control_mode_id" />
<result property="controlModeName" column="control_mode_name" />
<result property="cycle" column="cycle" />
<association column="program_id" property="programList" select="selectProgramInfosByProgramId"/>
</resultMap>
<select id="selectProgramInfosByProgramId" parameterType="long"
resultType="com.jsits.xk.model.Program">
select
<include refid="Program_Column_List" />
from program where program_id=#{id}
</select>
<select id="selectDayPlanInfosByPlanNo" parameterType="java.util.HashMap" resultMap="dayPlanResultMap" >
select * from (select
dp.day_plan_id,
trim(REGEXP_REPLACE(to_char(dp.time_duration,'0000'),'([[:digit:]]{2})([[:digit:]]{2})','\1:\2')) as time_duration,
pg.program_id,
pg.program_name,
so.order_name,
so.stage_order_id,
cm.control_mode_id,
cm.control_mode_name,
'120' as cycle
from day_plan dp
left join control_mode cm on dp.control_mode_id=cm.control_mode_id
left join program pg on dp.program_id=pg.program_id
left join stage_order so on dp.stage_order_id=so.stage_order_id
where dp.day_plan_no=#{dayPlanNo}
and dp.intersection_id=#{intersectionId}
)
group by (day_plan_id,time_duration,program_id,program_name,order_name,stage_order_id,control_mode_id,control_mode_name,cycle)
order by time_duration asc
</select>
<select id="selectWeekInfosByIntersectionId" parameterType="long"
resultMap="weekProgramResultMap">
select #{intersectionId} as intersection_id,week.plan_name,week.plan_id from
(
select '星期一' as plan_name,intersection_id,monday as plan_id from week_plan
union
select '星期二' as plan_name,intersection_id,tuesday as plan_id from week_plan
union
select '星期三' as plan_name,intersection_id,wendesday as plan_id from week_plan
union
select '星期四' as plan_name,intersection_id,thursday as plan_id from week_plan
union
select '星期五' as plan_name,intersection_id,friday as plan_id from week_plan
union
select '星期六' as plan_name,intersection_id,saturday as plan_id from week_plan
union
select '星期日' as plan_name,intersection_id,sunday as plan_id from week_plan
)week
left join day_plan dp on dp.day_plan_no=week.plan_id
where week.intersection_id=#{intersectionId}
group by week.plan_id,week.plan_name,week.intersection_id
order by week.plan_id
</select>
联合主键查询
- 在我们很多时候数据库中的主键并不是一个字段,而是通过两个甚至多个字段组合成主键。我们习惯上称之为联合主键。在多重映射中的代码中我们可以看到
weekProgramResultMap中级联selectDayPlanInfosByPlanNo这个sql查询。但是有意思的是column中并不是我们熟悉的一个字段。而是通过花括号做首尾,中间加入多个字段组成的一个字符串。这个就是我们本章节引入的概念---联合主键级联查询。column属性值我们分析一下可以看出intersectionId=INTERSECTION_ID和dayPlanNo=PLAN_ID组成的。我们可以看成是两个map,等号前是key等号后是value。key就是我们在新的select中引用的key,及#{key}方式获取。value就是原来的select查询获得的数据。也是通过value来查询新的数据的。这里就解决了我们上面基本映射章节说必须用#{id}的局限性。所以在上面中如何我们不想用#{id},那么需要修改column的传入风格{stageId=stage_list}就可以用#{stageId}
简单说明
工作遇到的需求,mybatis还有很多神操作。以后有机会更新。在mybatis中映射并不是仅仅字段这么简单。还有点逗风格的引用。这些以后看时间在更新。
常用标签
格言
人生贵知心,定交无暮早。 —— 袁中道
mybatis关联的更多相关文章
- Mybatis关联查询和数据库不一致问题分析与解决
Mybatis关联查询和数据库不一致问题分析与解决 本文的前提是,确定sql语句没有问题,确定在数据库中使用sql和项目中结果不一致. 在使用SpringMVC+Mybatis做多表关联时候,发现也不 ...
- MyBatis基础:MyBatis关联查询(4)
1. MyBatis关联查询简介 MyBatis中级联分为3中:association.collection及discriminator. ◊ association:一对一关联 ◊ collecti ...
- MyBatis关联查询,一对多关联查询
实体关系图,一个国家对应多个城市 一对多关联查询可用三种方式实现: 单步查询,利用collection标签为级联属性赋值: 分步查询: 利用association标签进行分步查询: 利用collect ...
- mybatis 关联查询实现一对多
场景:最近接到一个项目是查询管理人集合 同时每一个管理人还存在多个出资人 要查询一个管理人列表 每个管理人又包含了出资人列表 采用mybatis关联查询实现返回数据. 实现方式: 1 .在实体 ...
- MyBatis关联查询、多条件查询
MyBatis关联查询.多条件查询 1.一对一查询 任务需求; 根据班级的信息查询出教师的相关信息 1.数据库表的设计 班级表: 教师表: 2.实体类的设计 班级表: public class Cla ...
- Mybatis 关联对象不能输出的解决办法
Mybatis 关联对象不能输出的解决办法 1.如图所示,现在进行查询的时候并没有得到来自另一张表address项 2.我们进行如下配置: (1).在mybatis-config.xml 文件中配置, ...
- Mybatis关联查询之二
Mybatis关联查询之多对多 多对多 一.entity实体类 public class Student { private Integer stuid; private String stuname ...
- mybatis关联查询基础----高级映射
本文链接地址:mybatis关联查询基础----高级映射(一对一,一对多,多对多) 前言: 今日在工作中遇到了一个一对多分页查询的问题,主表一条记录对应关联表四条记录,关联分页查询后每页只显示三条记录 ...
- MyBatis关联查询和懒加载错误
MyBatis关联查询和懒加载错误 今天在写项目时遇到了个BUG.先说一下背景,前端请求更新生产订单状态,后端从前端接收到生产订单ID进行查询,然后就有问题了. 先看控制台报错: org.apache ...
- Mybatis关联查询(嵌套查询)
上一篇文章介绍了基于Mybatis对数据库的增.删.改.查.这一篇介绍下关联查询(join query). 三张表:user article blog 表的存储sql文件: /* Navicat My ...
随机推荐
- java 压缩导出多个excel
简单介绍下我实现的功能,首先是我的excel上传,它是以blob字段存储在oracel数据库中的,我实现的是循环遍历blob字段并使用io流进行打包下载,如有需要可自行修改 使用技术有,springM ...
- NFS服务
第1章 NFS介绍 1.1 NFS的概念 NFS是Network File System的缩写,即网络文件系统,它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录.NFS客户 ...
- 利用vertical-align实现行内元素对齐
实际项目中,常常会遇到一排行内元素对齐排列的需求,但是往往它们是这样的 我们想要的其实是这样的 曾经我一度不得不使用定位来实现我想要的位置效果,将父元素设置 position:relative ,行内 ...
- 基于socket.io打造hybrid调试页面
前言 参考的钉钉调试页面实现,仅供学习! 功能为: PC端编写代码,手机端执行 解决的痛点是: 避免了调试hybrid应用时重复写各种测试页面 源码与示例 源码 https://github.com/ ...
- Heap Sorting 总结 (C++)
各位读者,大家好. 因为算法和数据结构相关的知识都是在国外学的,所以有些词汇翻译的可能不准确,然后一些源代码的注释可能是英文的,如有给大家带来什么不方便,请见谅.今天我想写一下Heap相关的知识,从基 ...
- 微信小程序与Java后台的通信
一.写在前面 最近接触了小程序的开发,后端选择Java,因为小程序的代码运行在腾讯的服务器上,而我们自己编写的Java代码运行在我们自己部署的服务器上,所以一开始不是很明白小程序如何与后台进行通信的, ...
- Redis 高可用集群
Redis 高可用集群 Redis 的集群主从模型是一种高可用的集群架构.本章主要内容有:高可用集群的搭建,Jedis连接集群,新增集群节点,删除集群节点,其他配置补充说明. 高可用集群搭建 集群(c ...
- 命令模式(Command)
命令模式(Command) 命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行.这个过程好在,三者相互 ...
- TensorFlow —— Demo
import tensorflow as tf g = tf.Graph() # 创建一个Graph对象 在模型中有两个"全局"风格的Variable对象:global_step ...
- 第四届河南省ACM 节能 区间DP
1001: 节 能 时间限制: 1 Sec 内存限制: 128 MB 提交: 21 解决: 9 [提交][状态][讨论版] 题目描述 Dr.Kong设计的机器人卡多越来越聪明.最近市政公司交给卡多 ...