ResultMap结果集映射
多对一
-
按照查询嵌套处理:需要两个查询,被嵌套的<association>需要column以及select属性
-
按照结果嵌套处理:不需要column以及select属性
对于数据库的字段和pojo里面的字段一致时,不需要在繁琐的配置,只需要配置不一样的字段即可
<resultMap id="Orders" type="com.ahrtolia.entity.Order"> <id property="id" column="oId"></id> <result property="count" column="ocount"></result> <association property="product" javaType="com.ahrtolia.entity.Product"> <result property="name" column="name"></result> <result property="fileName" column="fileName"></result> <result property="price" column="price"></result> </association> </resultMap> <select id="getMyProductCar" resultMap="Orders"> select o.id as oId,o.count as ocount,p.name as name,p.fileName as fileName,p.price as price from orders as o,product as p where o.userId= #{userId} and o.productId = p.id and state = 0; </select>
<resultMap>
- id的值对应resultMap的值
- type为返回的类型
<result>和<id>都可以用
-
property(pojo类的字段)映射为column(数据库的列名)
<collection>
- property
- ofType表示集合里面的泛型类型
<association>用于处理对象
- property属性为当前pojo类里面的引用对象的类型
- column为property对应的字段(这里把对象看成普通列就好理解了)
- javaType为引用对象对应的pojo类
- select为当前resultMap对应的select查询的id
一对多差别不大
缓存(cache)
在mybatis.xml中配置
可以直接添加<cache>标签开启默认的二级缓存(mapper.xml当中配置)
二级缓存只生效于一个namespace
动态 SQL
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
if
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。比如:
<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select>
这条语句提供了一个可选的文本查找类型的功能。如果没有传入"title",那么所有处于"ACTIVE"状态的BLOG都会返回;反之若传入了"title",那么就会把模糊查找"title"内容的BLOG结果返回
如果想可选地通过"title"和"author"两个条件搜索该怎么办呢?首先,改变语句的名称让它更具实际意义;然后只要加入另一个条件即可。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select>
choose, when, otherwise
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
还是上面的例子,但是这次变为提供了"title"就按"title"查找,提供了"author"就按"author"查找,若两者都没有提供,就返回所有符合条件的BLOG(实际情况可能是由管理员按一定策略选出BLOG列表,而不是返回大量无意义的随机结果)。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
trim, where, set
前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。现在考虑回到"if"示例,这次我们将"ACTIVE = 1"也设置成动态的条件,看看会发生什么。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select>
如果这些条件没有一个能匹配上将会怎样?最终这条 SQL 会变成这样:
SELECT * FROM BLOG WHERE
这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:
SELECT * FROM BLOG WHERE AND title like 'someTitle'
这个查询也会失败。这个问题不能简单的用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不想再这样去写了。
MyBatis 有一个简单的处理,这在90%的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能得到想要的效果:
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select>
where 元素知道只有在一个以上的if条件有值的情况下才去插入"WHERE"子句。而且,若最后的内容是"AND"或"OR"开头的,where 元素也知道如何将他们去除。
如果 where 元素没有按正常套路出牌,我们还是可以通过自定义 trim 元素来定制我们想要的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它带来的结果就是所有在 prefixOverrides 属性中指定的内容将被移除,并且插入 prefix 属性中指定的内容。
类似的用于动态更新语句的解决方案叫做 set。set 元素可以被用于动态包含需要更新的列,而舍去其他的。比如:
<update id="updateAuthorIfNecessary"> update Author <set> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> <if test="bio != null">bio=#{bio}</if> </set> where id=#{id} </update>
这里,set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。
若你对等价的自定义 trim 元素的样子感兴趣,那这就应该是它的真面目:
<trim prefix="SET" suffixOverrides=","> ... </trim>
注意这里我们忽略的是后缀中的值,而又一次附加了前缀中的值。
foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
foreach 元素的功能是非常强大的,它允许你指定一个集合,声明可以用在元素体内的集合项和索引变量。它也允许你指定开闭匹配的字符串以及在迭代中间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
注意 你可以将一个 List 实例或者数组作为参数对象传给 MyBatis,当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中并以名称为键。List 实例将会以"list"作为键,而数组实例的键将是"array"。
到此我们已经完成了涉及 XML 配置文件和 XML 映射文件的讨论。下一部分将详细探讨 Java API,这样才能从已创建的映射中获取最大利益。
MyBatis常见问题合集
大于号、小于号在 sql 语句中的转换
使用 mybatis 时 sql 语句是写在 xml 文件中,如果 sql 中有一些特殊的字符的话,比如< ,<=,>,>=等符号,会引起 xml 格式的错误,需要替换掉,或者不被转义。 有两种方法可以解决:转义字符和标记 CDATA 块。
方式1、转义字符
<select id="searchByPrice" parameterType="Map" resultType="Product">
<!-- 方式1、转义字符 -->
select * from Product where price >= #{minPrice} and price <= #{maxPrice}
</select>
<!-- 方式2、CDATA -->
<![CDATA[select * from Product where price >= #{minPrice} and price <= #{maxPrice} ]]>
</select>
转义字符表
< = < > = > & = & ' = ' " = "
3、参数
Mapper 中需要用 @Param("queryDate")定义参数名称,sql 中用#{queryDate}使用参数,字符串也不需要引号。
参数判断和if的用法:
<if test="queryDate != null">
and queryDate >= #{queryDate}
</if>
when otherwise 就是 if else
<choose>
<when test="isDelete != null and isDelete == 0">
isDelete=0
</when>
<otherwise>
isDelete=1
</otherwise>
</choose>
如果要判断的字符串,则需要加引号
<when test="gender != null and gender == 'MALE'">
gender='MALE'
</when>
4.传入参数参数为0查询条件失效
4.1 场景再现
场景是这样的,需要做一个对账单查询,可以按金额范围进行查询,页面参数写完之后进行条件,输入0测试了无数次均失效。
4.2 原因解析
当页面参数为 0,传入到 mybatis 的 xml 中后,如果不是字符串,需指定数据类型,否则会被误认为 null
<if test="data.tatalAmount != null and data.totalAmount !='' ">
and total_Amount=#{data.totalAmount}
</if>
这种情况如果 totalAmount 为 0 时将被误认为是 null,里面的条件不会执行。正确的姿势如下
1.添加 0 判断
<if test="data.tatalAmount != null and data.totalAmount !='' or tatalAmount==0 ">
and total_Amount=#{data.totalAmount}
</if>
2.规定传入参数的类型
<if test="data.tatalAmount != null and data.totalAmount !='' ">
and total_Amount=#{data.totalAmount,jdbc.Type=DECIMAL}
</if>
标签:name,author,title,BLOG,Mybatis,where,like From: https://www.cnblogs.com/happy12123/p/16822435.html