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 ...
随机推荐
- python3随笔第一天
1.python 语言没有{},注重书写格式,注重空格的使用,书写python程序一定要注意代码对齐,代码格式对齐是python程序书写的生命: 2.python 分支判断格式 if 条件 : e ...
- 获取IP-linux(经典-实用)
Linux系统获取网卡ip 1.正宗的有6种取ip的方法 sed(3) +awk(2)+egrep(1) sed(替换): ( )\1 [^0-9.] 掐头|去尾 awk(分隔符): ...
- linux操作系统基础篇(四)
一.系统监控 1.TOP 命令 1) top命令的功能:top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. 2) 使用top命令列 ...
- 查看oracle数据库里哪些语句耗时最长或者效率最低
CPU: select * from (select v.sql_id, v.child_number, v.sql_text, v.elapsed_time, v.cpu_time, v.disk_ ...
- vsftpd 安装
vsftpd 安装 这里有最简洁的安装步骤 理想流程 [root@itdragon ~]# useradd ftpuser [root@itdragon ~]# passwd ftpuser Chan ...
- overflow-x: scroll;横向滑动详细讲解
overflow-x: scroll;横向滑动(移动端使用详解) css3 , ie8以上 <!DOCTYPE html> <html lang="en"> ...
- params SqlParameter[] commandParameters(转)
C#代码 ExecuteReader(string connectionString, CommandType commandType, string commandText, params Sql ...
- 把项目中的那些恶心的无处存储的大块数据都丢到FastDFS之快速搭建
在我们开发项目的时候,经常会遇到大块数据的问题(2M-100M),比如说保存报表中1w个人的ID号,他就像一个肿瘤一样,存储在服务器哪里都 觉得恶心,放在redis,mongodb中吧,一下子 ...
- EntityFramework For Mysql 动态切换数据源
1.简介 在工作中遇到一个问题.项目有三个数据库(三个数据库表结构一样),用户可以选择使用哪个数据库.其实就是动态切换数据库连接. 2.EntityFramework For Mysql 先来简单的介 ...
- markdown 字体颜色
Markdown是一种可以使用普通文本编辑器编写的标记语言,通过类似HTML的标记语法,它可以使普通文本内容具有一定的格式.但是它本身是不支持修改字体.字号与颜色等功能的! CSDN-markd ...