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

题目

  • 总体概述
  • 查询参数部分
    • 如何定义查询参数
    • 如何使用查询参数
  • 结果映射
    • 返回结果是单条已有实体类
    • 返回结果是多条已有实体类
    • 返回结果没有对应实体类
      • 将返回结果封装为Map
      • 使用`ResultMap`解决数据库表字段与实体类属性不匹配
      • 一对多结果映射
        • 方式一:使用collection处理一对多映射关系
        • 方式二:使用分步查询
      • 多对一结果映射
        • 方式一:级联属性赋值
        • 方式二:使用association处理映射关系
        • 方式三:分步查询
    • 其他问题
  • 动态SQL
    • `if标签`
    • `where 标签`
    • `choose、when、otherwise标签`
    • `foreach标签`
    • `SQL片段`

总体概述

使用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会自动为实体类属性赋值。


<select id="queryById" resultType="com.hjyp.mybatislearning.entity.Meet">
	select * from meettable where meet_id = #{id}
select> 

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

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

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

返回结果没有对应实体类

将返回结果封装为Map

任何查询都可以用Map来接收,因为对象本身也是一个map。这时接口的返回值类型为Map,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>

<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 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>

    
    <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 property="attachs"
                select="com.hjyp.mybatislearning.mapper.AttachMapper.queryById"
                column="meet_id">
        collection>
        
    resultMap>

    
    <select id="queryById" resultMap="meetAttachResultMap">
        select * from meettable where meet_id = #{id}
    select>
    
    
    <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>

    
    <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 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>

    
    <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>

    
    <select id="queryById" resultMap="meetAttachResultMap">
        select * from meettable where meet_id = #{id}
    select>

	
    <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


<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去掉


<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标签中内容的结束符


<delete id="deleteMoreByArray">
	delete from t_emp where eid in
	<foreach collection="eids" item="eid" separator="," open="(" close=")">
		#{eid}
	foreach>
delete>



<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片段

你可能感兴趣的:(MyBatis,mybatis,java,数据库)