2021-08-02 动态SQL,Html

动态SQL

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同
条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个
列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显
著地提升了这一特性的易用性。

if

用于进行条件判断, test 属性用于指定判断条件. 为了拼接条件, 在 SQL 语句后强行添加 1=1 的恒成立条件

<select id="sel" resultType="user">
select * from t_user where 1=1
<if test="username != null and username != ''"> and username=#{username}
</if>
<if test="password != null and password != ''"> and password=#{password}
</if>
</select>

<select id="findUserById" resultType="user">
    select * from user where 
        <if test="id != null">
               id=#{id}
        </if>
    and deleteFlag=0;
</select>
where

用于管理 where 子句. 有如下功能:

  1. 如果没有条件, 不会生成 where 关键字
  2. 如果有条件, 会自动添加 where 关键字
  3. 如果第一个条件中有 and, 去除之
<select id="sel" resultType="user">
select * from t_user
<where>
<if test="username != null and username != ''"> and username=#{username}
</if>
<if test="password != null and password != ''"> and password=#{password}
</if>
</where>
</select>
<select id="findUserById" resultType="user">
    select * from user 
        <where>
            <if test="id != null">
                id=#{id}
            </if>
            and deleteFlag=0;
        </where>
</select>
choose…when…otherwise
<select id="sel" resultType="user">
select * from t_user
<where>
<choose>
<when test="username != null and username != ''">
and username = #{username}
</when>
<when test="password != null and password != ''">
and password = #{password}
</when>
<otherwise> and 1=1 </otherwise>
</choose>
</where>
</select>

set

用于维护 update 语句中的 set 子句. 功能如下:

  1. 满足条件时, 会自动添加 set 关键字
  2. 会去除 set 子句中多余的逗号
  3. 不满足条件时, 不会生成 set 关键字
int updUser(User user);
<update id="updUser" parameterType="user">
update t_user
<set>
id=#{id},<!-- 防止所有条件不成立时的语法错误 -->
<if test="username != null and username != ''">
username=#{username},
</if>
<if test="password != null and password != ''">
password=#{password},
</if>
</set>
where id=#{id}
</update>

<update id="updateUser" parameterType="com.dy.entity.User">
    update user set 
        <if test="name != null">
            name = #{name},
        </if> 
        <if test="password != null">
            password = #{password},
        </if> 
        <if test="age != null">
            age = #{age}
        </if> 
        <where>
            <if test="id != null">
                id = #{id}
            </if>
            and deleteFlag = 0;
        </where>
</update>
trim

用于在前后添加或删除一些内容

  1. prefix, 在前面添加内容
  2. prefixOverrides, 从前面去除内容
  3. suffix, 向后面添加内容
  4. suffixOverrides, 从后面去除内容
<update id="updUser" parameterType="user">
update t_user
<!-- prefix: 前缀, 表示向前面添加内容 prefixOverrides: 从前面删除内容 suffix: 后缀,
表示向后面添加内容 suffixOverrides: 从后面删除内容 -->
<trim prefix="set" prefixOverrides="user" suffix="hahaha"
suffixOverrides=","> username=#{username},
</trim>
where id=#{id}
</update>
<!--********************************************-->
<trim prefix="WHERE" prefixOverrides="AND |OR ">
    ... 
</trim>
bind

用于对数据进行再加工, 用于模糊查询

<select id="sel" resultType="user">
select * from t_user
<where>
<if test="username!=null and username!=''">
<bind name="username" value="'%' + username + '%'" />
and username like #{username}
</if>
</where>
</select>

foreach

用于在 SQL 语句中遍历集合参数, 在 in 查询中使用

  1. collection: 待遍历的集合
  2. open: 设置开始符号
  3. item: 迭代变量
  4. separator: 项目分隔符
  5. close: 设置结束符
List<User> selIn(@Param("list") List<Integer> list);
<select id="selIn" parameterType="list" resultType="user">
select * from t_user where id in
<foreach collection="list" open="(" separator="," close=")"
item="item"> #{item} </foreach>
</select>

sql…include

sql用于提取 SQL 语句, include用于引用 SQL 语句

<sql id="mySql"> id, username, password </sql>

<select id="selIn" parameterType="list" resultType="user">
select
<include refid="mySql" />
from t_user where id in
<foreach collection="list" open="(" separator="," close=")"
item="item"> #{item}
</foreach>
</select>


列名和属性名不一致问题

如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自动匹配. 因此, 当数据库表的列名和类的属性名不一致时, 会导致查不到数据. 解决该问题可以有两种方式:

列别名

查询时, 可以通过列别名的方式将列名和属性名保持一致,继续使用自动映射, 从而解决该问题. 但是较为麻烦.

<select id="selAll" resultType="user">
select id id1, username username1, password password2 from t_user
</select>


使用resultMap

resultMap用于自定义映射关系, 可以由程序员自主制定列名和属性名的映射关系. 一旦使用 resultMap,表示不再采用自动映射机制.

<resultMap type="user" id="umap"> <!-- id用于映射主键 -->
<id column="id" property="id1" /> <!-- 非主键使用result映射 -->
<result column="username" property="username1" />
<result column="password" property="password1" />
</resultMap>
<select id="selAll" resultMap="umap"> select * from t_user </select>

关系映射查询

数据库中表与表之间的关系:
一对一 (人->身份证)
一对多 (夏令营->学生)
多对一 (学生->班级)
多对多 (学生->课程)

resultMap 的关联方式实现多表查询(一对一|多对一)
  1. 在 StudentMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应班级的信息.
  2. 通过resultMap标签定义映射关系, 并通过association标签指定对象属性的映射关系. 可以把association标签看成一个resultMap标签使用. javaType 属性表示当前对象, 可以写全限定路径或别名.

学生类中添加一个班级类型的属性 :

public class Student implements Serializable{
private int id;
private String name;
private int age;
private String gender;
private int cid;
private Clazz cls;
}

StudentMapper:

<resultMap type="student" id="smap">
<id property="id" column="sid" />
<result property="name" column="sname" />
<result property="age" column="age" />
<result property="gender" column="gender" />
<result property="cid" column="cid" />
<association property="cls" javaType="clazz">
<id property="id" column="cid" />
<result property="name" column="cname" />
<result property="room" column="room" />
</association>
</resultMap>
<select id="selAll" resultMap="smap">
select s.id sid, s.name sname,
s.age, s.gender, c.id cid, c.name cname, c.room from t_student s left
join t_class c on s.cid=c.id
</select>

resultMap 的关联方式实现多表查询(一对 多)
  1. 在 ClazzMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应学生的信息.
  2. 通过resultMap定义映射关系, 并通过collection标签指定集合属性泛型的映射关系. 可以collection标签看成一个resultMap标签使用. ofType 属性表示集合的泛型, 可以写全限定路径或别名.

班级类中添加一个List容器存储学生类型 的数据 :

public class Clazz implements Serializable{
private int id;
private String name;
private int roomNum;
private List<Student> stus;
}

ClazzMapper.xml:

<mapper namespace="com.xxxx.mapper.ClazzMapper">
<resultMap type="clazz" id="cmap">
<id property="id" column="cid" />
<result property="name" column="cname" />
<result property="room" column="room" />
<collection property="stus" javaType="list"
ofType="student">
<id property="id" column="sid" />
<result property="name" column="sname" />
<result property="age" column="age" />
<result property="gender" column="gender" />
<result property="cid" column="cid" />
</collection>
</resultMap>
<select id="selAll" resultMap="cmap">
select c.id cid, c.name cname,
c.room, s.id sid, s.name sname, s.age, s.gender from t_student s right
join t_class c on s.cid=c.id </select>
</mapper>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值