MyBatis笔记-基础的查询参数和查询结果封装

总体概述

使用MyBatis个人认为分为以下几大块

  • 配置,包括所扫描的mapper位置、是否开启驼峰、数据库连接池信息等
  • 如何使用查询参数
  • 如何处理返回结果
  • 动态SQL,方便编写查询条件和批量操作

其中如何使用查询参数和处理返回结果部分都在xml文件中进行定义。

查询参数部分

如何定义查询参数

查询参数一般有两种情况:

  • 直接传入一个对象;
  • 传入多个字段;

第一种情况我们不需要任何注解,直接在mapper方法中传入对象,然后在sql语句中直接使用该对象的属性即可;

// 接口声明,根据实体查询会议
Meet queryByMeet(Meet meet);

// 在xml文件中使用
<!-- 传入一个实体,直接使用实体字段 -->
<select id="queryByMeet" resultType="com.hjyp.mybatislearning.entity.Meet">
    select * from meettable where meet_id = #{meetId}
</select>

第二种情况可以使用@Param()注解表示每个参数,底层会封装为一个map对象,这样可以在xml文件中根据名称直接使用。

// 接口声明,根据id查询会议
Meet queryById(@Param("id") Integer id);

// 在xml文件中使用
<!-- 根据id查询 -->
<select id="queryById" resultType="com.hjyp.mybatislearning.entity.Meet">
    select * from meettable where meet_id = #{id}
</select>

如何使用查询参数

使用查询参数一般通过两种方式#{}, ${}

#{}会根据参数的类型自动填充,如果是字符串会自动加上引号,不会引起SQL注入,日常情况下多使用这种方式。

${}是字符串拼接,不会自动加引号,如果是字符串类型或者日期类型的字段进行赋值时,需要手动加引号。常用的方式有三种:

  • 模糊查询:因为模糊查询的条件一般是字符串类型,但我们不能使用#{},因为这样会自动带上引号。若使用like %#{content}%则匹配条件为like %'content'%,应该使用like %${content}%,匹配条件为like %content%,这样才是正确的。
  • 批量删除:批量删除一般会传过来一个string类型的字符串,内容为删除内容的id,比如"1, 2, 3"。这个时候只能使用代码delete from t_table where id in (${ids})。因为这样不会加引号,可以正确删除。
  • 动态设置表名:有时表名会作为参数传入,此时也只能使用${},只有这样才不会额外多一个引号。select * from ${table_name}

其实还有另一种模糊查询方法更常见也更安全,不会sql注入,即使用字符串的自动拼接功能,代码为like "%"#{content}"%"

结果映射

返回结果是单条已有实体类

如果返回结果已有对应的实体类,那么直接在sql文件中指定resultType就可以了。Mybatis会自动为实体类属性赋值。

<!-- 根据id查询 -->
<select id="queryById" resultType="com.hjyp.mybatislearning.entity.Meet">
	select * from meettable where meet_id = #{id}
</select> 

注意:对于没有查询出来的字段会直接设为null

返回结果是多条已有实体类

对于返回结果是多条时,接口返回值用List<Entity>接收,xml文件还是指定实体类型即可。

返回结果没有对应实体类

将返回结果封装为Map

任何查询都可以用Map来接收,因为对象本身也是一个map。这时接口的返回值类型为Map<String, Object>,xml文件的resultType='java.util.Map'

接口定义

// 根据实体查询会议
Map<String, Object> queryByMeet(Meet meet);

xml文件定义

<!-- 传入一个实体,直接使用实体字段 -->
<select id="queryByMeet" resultType="java.util.Map">
	select * from meettable where meet_id = #{meetId}
</select>

使用ResultMap解决数据库表字段与实体类属性不匹配

我们可以使用resultMap自定义返回结果,在resultMap中绑定属性名与字段名。

resultMap是一个标签,该标签有id属性:用来唯一标识自定义结果映射; type属性:用来指定实体类型。

idresultMap的子标签,用来标识主键;result也是resultMap的子标签。

子标签拥有property属性:用来指定实体类的字段名;column属性:用来指定表的列名;

注意:使用自定义resultMap时,即使属性名和列名一致,也是需要显式指定的,不可以省略!

<resultMap id="empResultMap" type="Emp">
	<id property="eid" column="eid"></id>
	<result property="empName" column="emp_name"></result>
	<result property="age" column="age"></result>
	<result property="sex" column="sex"></result>
	<result property="email" column="email"></result>
</resultMap>
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultMap="empResultMap">
	select * from t_emp
</select>

一对多结果映射

方式一:使用collection处理一对多映射关系
  • ofType:指定集合里的实体类型
<resultMap id="meetAttachResultMap" type="com.hjyp.mybatislearning.entity.Meet">
        <id property="meetId" column="meet_id"></id>
        <result property="meetTime" column="meet_time"></result> 
        <result property="meetPlace" column="meet_place"></result> 
        <result property="meetTheme" column="meet_theme"></result> 
        <result property="meetReporter" column="meet_reporter"></result> 
        <result property="meetReporterId" column="meet_reportor_id"></result> 
        <result property="meetBelongRole" column="meet_belong_role"></result> 
        <result property="lastUpdatetime" column="last_updatetime"></result> 
        <!-- 使用collection-->
        <collection property="attachs" ofType="com.hjyp.mybatislearning.entity.Attach">
            <id property="attachId" column="attach_id"></id>
            <result property="attachName" column="attach_name"></result> 
            <result property="downloadUrl" column="download_url"></result> 
            <result property="lastUpdatetime" column="last_updatetime"></result> 
        </collection>
        
    </resultMap>

    <!-- 根据id查询会议 -->
    <select id="queryById" resultMap="meetAttachResultMap">
        select * from meettable inner join attachtable on attachtable.meet_id = meettable.meet_id where meettable.meet_id = #{id}
    </select>
方式二:使用分步查询

和多对一类似,只不过子标签换成了collection

  • property: 对应的属性字段
  • select:第二个查询语句的mapper所在包和方法
  • column:第二个查询语句所用到的条件
<resultMap id="meetAttachResultMap" type="com.hjyp.mybatislearning.entity.Meet">
        <id property="meetId" column="meet_id"></id>
        <result property="meetTime" column="meet_time"></result> 
        <result property="meetPlace" column="meet_place"></result> 
        <result property="meetTheme" column="meet_theme"></result> 
        <result property="meetReporter" column="meet_reporter"></result> 
        <result property="meetReporterId" column="meet_reportor_id"></result> 
        <result property="meetBelongRole" column="meet_belong_role"></result> 
        <result property="lastUpdatetime" column="last_updatetime"></result> 
        <!-- 使用collection的分阶段查询-->
        <collection property="attachs"
                select="com.hjyp.mybatislearning.mapper.AttachMapper.queryById"
                column="meet_id">
        </collection>
        
    </resultMap>

    <!-- 根据id查询会议 -->
    <select id="queryById" resultMap="meetAttachResultMap">
        select * from meettable where meet_id = #{id}
    </select>
    
    <!-- 根据id查询附件 -->
    <select id="queryById" resultType="com.hjyp.mybatislearning.entity.Attach">
        select * from attachtable where meet_id = #{meetId}
    </select>

多对一结果映射

方式一:级联属性赋值

使用字段.属性的方法来指定,还是用result子标签,property指定属性名,column指定列名

<resultMap id="meetAttachResultMap" type="com.hjyp.mybatislearning.entity.Meet">
        <id property="meetId" column="meet_id"></id>
        <result property="meetTime" column="meet_time"></result> 
        <result property="meetPlace" column="meet_place"></result> 
        <result property="meetTheme" column="meet_theme"></result> 
        <result property="meetReporter" column="meet_reporter"></result> 
        <result property="meetReporterId" column="meet_reportor_id"></result> 
        <result property="meetBelongRole" column="meet_belong_role"></result> 
        <result property="lastUpdatetime" column="last_updatetime"></result> 
        <!-- 级联方式映射 -->
        <result property="attach.attachName" column="attach_name"></result> 
        <result property="attach.downloadUrl" column="download_url"></result> 
        <result property="attach.lastUpdatetime" column="last_updatetime"></result> 
    </resultMap>

    <!-- 根据id连表查询 -->
    <select id="queryById" resultMap="meetAttachResultMap">
        select * from meettable inner join attachtable on attachtable.meet_id = meettable.meet_id where meettable.meet_id = #{id}
    </select> 
方式二:使用association处理映射关系
  • association: 子标签专门用来处理多对一关系
  • property:需要处理的映射关系的实体属性名
  • javaType:该属性的类型

注意:使用association需要通过javaType指定属性的类型

<resultMap id="meetAttachResultMap" type="com.hjyp.mybatislearning.entity.Meet">
        <id property="meetId" column="meet_id"></id>
        <result property="meetTime" column="meet_time"></result> 
        <result property="meetPlace" column="meet_place"></result> 
        <result property="meetTheme" column="meet_theme"></result> 
        <result property="meetReporter" column="meet_reporter"></result> 
        <result property="meetReporterId" column="meet_reportor_id"></result> 
        <result property="meetBelongRole" column="meet_belong_role"></result> 
        <result property="lastUpdatetime" column="last_updatetime"></result> 
        <!-- association子标签处理 , javaType是显式指定该实体属性的类型-->
        <association property="attach" javaType="com.hjyp.mybatislearning.entity.Attach">
            <id property="attachId" column="attach_id"></id>
            <result property="attachName" column="attach_name"></result> 
            <result property="downloadUrl" column="download_url"></result> 
            <result property="lastUpdatetime" column="last_updatetime"></result> 
        </association>
        
    </resultMap>

    <!-- 根据id连表查询 -->
    <select id="queryById" resultMap="meetAttachResultMap">
        select * from meettable inner join attachtable on attachtable.meet_id = meettable.meet_id where meettable.meet_id = #{id}
    </select>  
方式三:分步查询

先根据会议ID查出会议,再根据附件ID查出附件,其实是两个查询语句

  • property: 对应的属性字段
  • select:第二个查询语句的mapper所在包和方法
  • column:第二个查询语句所用到的条件
<resultMap id="meetAttachResultMap" type="com.hjyp.mybatislearning.entity.Meet">
        <id property="meetId" column="meet_id"></id>
        <result property="meetTime" column="meet_time"></result> 
        <result property="meetPlace" column="meet_place"></result> 
        <result property="meetTheme" column="meet_theme"></result> 
        <result property="meetReporter" column="meet_reporter"></result> 
        <result property="meetReporterId" column="meet_reportor_id"></result> 
        <result property="meetBelongRole" column="meet_belong_role"></result> 
        <result property="lastUpdatetime" column="last_updatetime"></result> 
        <!-- 使用分步查询 -->
        <association property="attach"
                select="com.hjyp.mybatislearning.mapper.AttachMapper.queryById"
                column="meet_id">
        </association>
        
    </resultMap>

    <!-- 根据id查询会议 -->
    <select id="queryById" resultMap="meetAttachResultMap">
        select * from meettable where meet_id = #{id}
    </select>

	<!-- 根据id查询附件 -->
    <select id="queryById" resultType="com.hjyp.mybatislearning.entity.Attach">
        select * from attachtable where meet_id = #{meetId}
    </select>  

其他问题

  • 当实体类中的某个字段在数据库中不存在时,只要保证插入语句不出现该字段就可以了。但是在MybatisPlus中由于是以实体作为操作单元,所以要使用注解忽略不存在的属性。
  • 当数据库没有查询出该字段时,实体类一般为null

动态SQL

动态SQL可以根据特定条件动态拼接SQL语句,比如查询时where语句后面的各种条件。常见的标签有ifwheretrimchoose、when、otherwiseforeach

if标签

if标签用来判断某个属性是否为空,如果不为空可以拼接相应的语句。

使用if时可以在where语句后加上一个恒成立条件,比如1=1,然后把每条分支语句前加个 and

<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
	select * from t_emp where 1=1
	<if test="empName != null and empName !=''">
		and emp_name = #{empName}
	</if>
	<if test="age != null and age !=''">
		and age = #{age}
	</if>
	<if test="sex != null and sex !=''">
		and sex = #{sex}
	</if>
	<if test="email != null and email !=''">
		and email = #{email}
	</if>
</select>

where 标签

前面只使用if标签时,我们加了一个恒成立条件,但如果配合使用where标签,就不需要加恒成立的条件了。

  • 如果where标签的内容为空,那么不会在最后的sql语句中加where条件

  • 若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and/or去掉

<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
	select * from t_emp
	<where>
		<if test="empName != null and empName !=''">
			emp_name = #{empName}
		</if>
		<if test="age != null and age !=''">
			and age = #{age}
		</if>
		<if test="sex != null and sex !=''">
			and sex = #{sex}
		</if>
		<if test="email != null and email !=''">
			and email = #{email}
		</if>
	</where>
</select>

choose、when、otherwise标签

作用和if…else if… else一样,选择一个合适的条件执行

<select id="getEmpByChoose" resultType="Emp">
	select * from t_emp
	<where>
		<choose>
			<when test="empName != null and empName != ''">
				emp_name = #{empName}
			</when>
			<when test="age != null and age != ''">
				age = #{age}
			</when>
			<when test="sex != null and sex != ''">
				sex = #{sex}
			</when>
			<when test="email != null and email != ''">
				email = #{email}
			</when>
			<otherwise>
				did = 1
			</otherwise>
		</choose>
	</where>
</select>

foreach标签

  • collection:设置要循环的数组或集合
  • item:表示数组或集合的每一项数据
  • separator:每一项之间的分隔符
  • open:设置foreach标签中内容的开始符
  • close:设置foreach标签中内容的结束符
<!--int deleteMoreByArray(Integer[] eids);-->
<!--批量删除-->
<delete id="deleteMoreByArray">
	delete from t_emp where eid in
	<foreach collection="eids" item="eid" separator="," open="(" close=")">
		#{eid}
	</foreach>
</delete>

<!--int insertMoreByList(@Param("emps") List<Emp> emps);-->
<!--批量新增-->
<insert id="insertMoreByList">
	insert into t_emp values
	<foreach collection="emps" item="emp" separator=",">
		(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)
	</foreach>
</insert>

SQL片段

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值