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_IDdayPlanNo=PLAN_ID组成的。我们可以看成是两个map,等号前是key等号后是value。key就是我们在新的select中引用的key,及#{key}方式获取。value就是原来的select查询获得的数据。也是通过value来查询新的数据的。这里就解决了我们上面基本映射章节说必须用#{id}的局限性。所以在上面中如何我们不想用#{id},那么需要修改column的传入风格{stageId=stage_list}就可以用#{stageId}

简单说明

工作遇到的需求,mybatis还有很多神操作。以后有机会更新。在mybatis中映射并不是仅仅字段这么简单。还有点逗风格的引用。这些以后看时间在更新。

常用标签

格言

人生贵知心,定交无暮早。 —— 袁中道

mybatis关联的更多相关文章

  1. Mybatis关联查询和数据库不一致问题分析与解决

    Mybatis关联查询和数据库不一致问题分析与解决 本文的前提是,确定sql语句没有问题,确定在数据库中使用sql和项目中结果不一致. 在使用SpringMVC+Mybatis做多表关联时候,发现也不 ...

  2. MyBatis基础:MyBatis关联查询(4)

    1. MyBatis关联查询简介 MyBatis中级联分为3中:association.collection及discriminator. ◊ association:一对一关联 ◊ collecti ...

  3. MyBatis关联查询,一对多关联查询

    实体关系图,一个国家对应多个城市 一对多关联查询可用三种方式实现: 单步查询,利用collection标签为级联属性赋值: 分步查询: 利用association标签进行分步查询: 利用collect ...

  4. mybatis 关联查询实现一对多

    场景:最近接到一个项目是查询管理人集合  同时每一个管理人还存在多个出资人   要查询一个管理人列表  每个管理人又包含了出资人列表 采用mybatis关联查询实现返回数据. 实现方式: 1 .在实体 ...

  5. MyBatis关联查询、多条件查询

    MyBatis关联查询.多条件查询 1.一对一查询 任务需求; 根据班级的信息查询出教师的相关信息 1.数据库表的设计 班级表: 教师表: 2.实体类的设计 班级表: public class Cla ...

  6. Mybatis 关联对象不能输出的解决办法

    Mybatis 关联对象不能输出的解决办法 1.如图所示,现在进行查询的时候并没有得到来自另一张表address项 2.我们进行如下配置: (1).在mybatis-config.xml 文件中配置, ...

  7. Mybatis关联查询之二

    Mybatis关联查询之多对多 多对多 一.entity实体类 public class Student { private Integer stuid; private String stuname ...

  8. mybatis关联查询基础----高级映射

    本文链接地址:mybatis关联查询基础----高级映射(一对一,一对多,多对多) 前言: 今日在工作中遇到了一个一对多分页查询的问题,主表一条记录对应关联表四条记录,关联分页查询后每页只显示三条记录 ...

  9. MyBatis关联查询和懒加载错误

    MyBatis关联查询和懒加载错误 今天在写项目时遇到了个BUG.先说一下背景,前端请求更新生产订单状态,后端从前端接收到生产订单ID进行查询,然后就有问题了. 先看控制台报错: org.apache ...

  10. Mybatis关联查询(嵌套查询)

    上一篇文章介绍了基于Mybatis对数据库的增.删.改.查.这一篇介绍下关联查询(join query). 三张表:user article blog 表的存储sql文件: /* Navicat My ...

随机推荐

  1. 设计模式的征途—21.迭代器(Iterator)模式

    我们都用过电视机遥控器,通过它我们可以进行开机.关机.换台.改变音量等操作.我们可以将电视机看做一个存储电视频道的集合对象,通过遥控器可以对电视机中的频道集合进行操作,例如返回上一个频道.跳转到下一个 ...

  2. STM32基础问题分析——PWM配置

    STM32基础问题分析--PWM配置 在使用STM32F103产生固定频率.固定占空比的PWM波时,虽然有官方以及众多开发板提供的例程,但是关于有点问题并没有说的很清晰,并且<STM32F10X ...

  3. Spring集成Quartz完成定时任务

    在JavaEE系统中,我们经常会用到定时任务,比如每天晚上凌晨之后跑批处理或者是每天某个时刻群发消息等等. 我们可以使用java.util.Timer结合java.util.TimerTask来去完成 ...

  4. 深入理解Java内置锁和显式锁

    synchronized and Reentrantlock 多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两 ...

  5. app打包常用操作

    1.修改appId android:打开build.gradle文件 找到defaultConfig{applicationId 'ceshi'} 修改测试.android studio会提示. Gr ...

  6. 《Maven实战》 第7章 生命周期与插件

    7.1什么是生命周期 软件开发人员每天都在对项目进行清理.编译.测试及部署,Maven生命周期是对所有构建过程进行抽象和统一,含项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等几 ...

  7. 在ThinkPHP中使用常量解决路由常规地址不安全传送数据问题

    在ThinkPHP搭建项目的同时,会考虑到后期对静态页面的维护问题, 在项目的不断完善的同时,会有大量图片,css文件,以及js文件等一些容易修改.添加.或者删除的资源 如果在中后期对各个静态页面,j ...

  8. springmvc中对日期格式化的处理

    @DateTimeFormat(pattern="yyyy-MM-dd") 返回的时候java.util.Date pattern="yyyy-MM-dd"必须 ...

  9. python3中的编码与解码(超好理解)

    编码和解码是针对数据而言的,数据能干什么呢?无非就是用来显示,储存和传输的: 储存和传输数据当然是希望数据越小越好,所以发明了utf-8这种数据编码显示:它智能将英文用一个字节表示,欧洲的字符用两个字 ...

  10. HDU4508--完全背包

    湫湫系列故事--减肥记I Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...