您的位置:首页 > 数据库

Mybatis 输入输出映射和动态SQL

2017-11-15 21:23 417 查看

Mybatis 输入输出映射和动态SQL

输入映射

输入的元素可以是简单类型, pojo 对象,也可以是map

如果查询的判断条件很复杂,这时我们一般采用pojo对象来封装需要的判断元素,将封装好的pojo对象,传入

输出映射

输出的元素可以是简单类型, pojo 对象,也可以是map

输出映射可以采用 resultType 进行映射, 指定返回的对象,但是使用此有几个限制:

使用resultType进行输出映射,只有查询出来的列名和返回的pojo对象中的属性名一致,该列才可以映射成功。

如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。

只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

使用 resultMap 完成高级输出结果映射

如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

1、定义resultMap

2、使用resultMap作为statement的输出映射类型

<!-- id 为 此resultMap 的唯一标识,在下面的select 语句中 的 resultMap 处使用,
type 为Java编写的返回的pojo对象的引用,此处使用的是别名,别名在sqlMapConfig中定义-->
<resultMap id="UserCustomer" type="UserCustomer">
<id property="customer_id" column="id"/>
<result property="customer_username" column="username"/>
<result property="customer_address" column="address"/>
<result property="customer_sex" column="sex"/>
<result property="customer_birthday" column="birthday"/>
</resultMap>


<!--使用动态字符串拼接-->
<select id="queryUserByUserQueryVo" parameterType="com.dustin.dao.UserQueryVo" resultMap="UserCustomer">
select * from User
<where>
<!-- 判断条件是什么-->
<if test="user.username != null and user.username != ''">
and username = #{user.username}
</if>
<if test="user.sex != null and user.sex != ''">
and sex = #{user.sex}
</if>
<!-- collection 是传进来的参数名称, item 是当前变量, open 是语句以什么开头,
close 是以什么结尾, separator 是遍历每一个元素的分隔符-->
<if test="ids != null">
<foreach collection="ids" item="id" open=" and id in (" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>


级联功能

这个功能是干什么的呢, 比如 我们要查用户的个人信息,以及他的订单信息,个人信息在一个表中, 订单信息在一个表中,则需要返回的resultMap 中则会有一个订单信息 List , 如何根据用户id查询订单信息并将订单信息填充到 resultMap中呢? 此时级联功能可以起到作用。

mybatis 中级联分为三种:

* association 代表一对一的关系 *

* collection 代表一对多的关系 *

* discriminator 鉴别器,根据条件选择哪个类作为实例*

<resultMap>
.....
<!-- 含义property 为返回的pojo对象中的变量名
column 为 传入的条件字段,多个字段可以要给你逗号隔开
select 为 要执行的SQL语句,一般是要执行的方法的引用 -->
<!-- 1:1 -->
<association property = 'studentSelfcard' column = 'id' select = 'com.learn.mapper.studentSelfcard.ffindStudentSelfcardbystudentId'/>

<!-- 1:N -->
<collection property = '' column = '' select = ''/>

<!-- 鉴别器 分为两步, 第一步先说明,给出选择条件 -->
<discriminator javaType = "int" coloum = 'sex'>
<case value = '1' resultMap = "maleStudentMap"/>
<case value = '2' resultMap = "femaleStudentMap"/>
</discriminator>
<!-- id 为上面进行选择的唯一标识
type 为返回的查询结果对应的类
extends 继承id为studentMap的映射配置 -->
<resultMap id = "maleStudentMap" type = "XX.XX.XX.maleStudentBean"  extends = "studentMap">
</resultMap>
<resultMap id = "femaleStudentMap" type = "XX.XX.XX.maleStudentBean"  extends = "studentMap">
</resultMap>


级联的缺陷 性能上会出现N+1问题

N+1 问题:

你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。

对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。

这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。

Mybatis 的解决方案: 延迟加载 能大大提高数据库的性能,因为单标查询的速度要比多表查询快

两个参数:

设置 lazzyLoadingEnabled = true 开启延迟加载功能

设置 aggeressiveLazzyLoading = false 将代表着 延迟加载下的 按需加载,即调用时才会进行加载

如果只设置第一个参数,开启延迟加载,默认情况下的延迟加载是按照层级加载的,而设置了第二个参数之后,代表着按需要加载,只有调用的时候才会进行加载

第一层: 学生

第二层: 课程成绩, 学生证

第三层: 课程

比如,当调用课程成绩的时候,如果不设置第二个参数,则 学生证的相关信息也会被加载返回, 设置了第二个参数,则只会返回课程成绩

延迟加载的实现原理是通过动态代理实现的,会生成一个动态代理对象,里面保存着相关的SQL参数,一旦使用这个代理对象的方法,它会进入方法中通过发送SQL和参数就可以把对应的结果从数据库中查找回来。

动态SQL

mybatiss 提供了丰富的语法实现SQL的动态拼接

if

<!-- test 判断条件是什么 , and username .... 是需要拼接的SQL语句-->
<if test="user.username != null and user.username != ''">
and username = #{user.username}
</if>


choose when otherwise 实现if else 功能

<choose>
<when test="user.username != null and user.username != ''">
and username = #{user.username}
</when>
<when test="user.username == null or user.username == ''">
and !(1=1)
</when>
<otherwise>
and !(1=1)
</otherwise>
<choose>


trim where set 等标签, set 标签完成只更新某些字段,而不是全部的字段的功能

update User
<set>
<if test="user.username != null and user.username != ''">
username = #{user.username}
</if>
<if test="user.sex != null and user.sex != ''">
sex = #{user.sex}
</if>
</set>
where is = #{user.id}
<!-- trim 是过滤功能, 含义是消除掉set标签中的全部 逗号  -->
<trim prefix = "set" suffixOverridies = ','>
</trim>


foreach 常常用在in 查询之中

<!--使用动态字符串拼接-->
<select id="queryUserByUserQueryVo" parameterType="com.dustin.dao.UserQueryVo" resultMap="UserCustomer">
select * from User
<!-- where 标签 里面书写if 语句,可以自动将 第一个条件语句中的 = 去掉 -->
<where>
<!-- collection 是传进来的参数名称, item 是当前变量, open 是语句以什么开头,
close 是以什么结尾, separator 是遍历每一个元素的分隔符-->
<if test="ids != null">
<foreach collection="ids" item="id" open=" and id in (" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>


bind 这个标签是定义一个上下文变量,以便于我们在sql 语句中去使用,比如模糊查询之中 name 是我们起的名字, value 是这个变量的值

<select id="queryUserByUserQueryVo" parameterType="com.dustin.dao.UserQueryVo" resultMap="UserCustomer">
<bind name = "username" value = "'%' + user.username + '' "/>
select * from User where username like #{username}
</select>


sql 片段 (为了达到sql语句的复用)

<select id="queryUserByUserQueryVo" parameterType="com.dustin.dao.UserQueryVo" resultMap="UserCustomer">
select * from User
<where>
<!--引用sql 的ID, 如果sql片段不在本地mapper中,需要加上前缀 namespace -->
<include refid="queryUserByVo"/>
</where>
</select>


<!-- sql 片段, 方便sql语句的复用 ,一般是基于单表来定义sql片段 -->
<sql id="queryUserByVo">
<!-- 判断条件是什么-->
<if test="user.username != null and user.username != ''">
and username = #{user.username}
</if>
<!-- 其他语句接着往下写就行 -->
</sql>


说明: 本文大部分内容都是跟随者传播智课的教学视频学习而来,可以看做是翻译文章,只是自己吸收之后又书写一遍,加深自己的知识理解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: