Spring Boot 整合 Mybatis笔记(二):如何正确书写满足基本操作 的Mybatis Mapper.xml文件

一、在mapper中几个常用元素

1. select –映射查询语句
2. insert –映射插入语句
3. update –映射更新语句
4. delete –映射删除语句
5. sql    –可以重用的 SQL 块,也可以被其他语句引用
6. bind   –将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值
7. resultMap   –将数据库查询结果集映射到对象中

二 、基本结构
  <?xml version="1.0" encoding="UTF-8" ?>
  <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  <mapper namespace="com.example.demo.dao.UserDao">
  	....
  </mapper>
namespace :是用于绑定Dao接口的,即面向接口编程。当你的namespace绑定接口后,你可以不用写接口实现类,mybatis会通过该绑定自动帮你找到对应要执行的SQL语句.注意这里需要完整的路径,不要写错,不然会报找不到的错误。
三、常用标签元素使用
1.select
  <!--- 根据用户id查询用户信息,接收一个integer类型的参数,并将返回结果映射 -->
  <select id="findById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
   select * from user where 1=1
   <if test="_parameter != null">
      and _id = #{id,jdbcType=Integer}
   </if>
  </select>

语句中使用到的属性说明
1). id 在命名空间中唯一的标识符,可以被用来引用这条语句,必须要和Dao接口中的接口名一致
2). parameterType 指定输入参数的类型 (关于参数传递、接收在后面会详细解析)
3). resultMap 引用外部的 resultMap,注意 resultMap 或 resultType不能同时使用.

< if >
  在上面的查询中,使用了 if 元素 ,主要是为了判断入参是否为null,然后拼接后面的sql语句,如果你能确保上层传进来的参数不可能为空,可以不用。
_parameter
  这是mybatis的内置参数,如果传进来的参数为一个参数,那这个就代表该参数,如果为多个参数就可以通过下标获取,如:< if test=’_parameter.get(“0”).name != null’ > username = #{0.name},这样就是获取第一个对象参数的name属性,基本类型的话,直接_parameter.get(0)就好。
#{} (推荐)
  在mapper中有两种获取参数的方式:
#{}是占位符,传入的参数在SQL中显示为字符串,可有效防止sql注入,但是在order by后不能使用

-------关于参数传递、接收在后面会详细解析


其他属性

属性说明
resultType指定输出结果的类型,在select中如果查询结果是集合,那么也表示集合中每个元素的类型
flushCache将其设置为 true,不论语句什么时候被调用,都会导致缓存被清空。默认值:false。
useCache将其设置为 true, 将会导致本条语句的结果被缓存。默认值: true。
timeout这个设置驱动程序等待数据库返回请求结果,并抛出异常时间的最大等待值。默认不设置(驱动自行处理)
fetchSize这是暗示驱动程序每次批量返回的结果行数。默认不设置(驱动自行处理)。
statementTypeSTA TEMENT,PREPARED 或 CALLABLE 的一种。这会让 MyBatis 使用选择使用 Statement,PreparedStatement 或 CallableStatement。默认值:PREPARED。
resultSetTypeFORWARD_ONLY|SCROLL_SENSITIVE|SCROLL_INSENSITIVE 中的一种。默认是不设置(驱动自行处理)。
2.insert
  <!-- mysql插入数据后,获取自增id,并将id写入入参绑定的属性上 -->
  <insert id="insert" parameterType="com.example.demo.pojo.User" >
  	<!--获取插入数据后的自增主键,并将结果写入传入对象的属性中去-->
   <selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
       SELECT LAST_INSERT_ID() as id
   </selectKey>
   insert into user
   <trim prefix="(" suffix=")" suffixOverrides=",">
       <if test="username != null">
           username,
       </if>
       <if test="password != null">
           password,
       </if>
   </trim>
   <trim prefix="values (" suffix=")" suffixOverrides=",">
       <if test="username != null">
           #{username},
       </if>
       <if test="password != null">
           #{password},
       </if>
   </trim>

selectKey
有时候新增一条数据,知道新增成功即可,但是有时候,需要这条新增数据的主键,以便逻辑使用,再将其查询出来明显不符合要求,效率变低了。 而该标签主要用于插入数据时返回会将 SELECT LAST_INSERT_ID()的结果放入到传入的model的主键里面,以便后续使用。
主要属性:

属性说明
keyProperty对应的model中的主键的属性名,这里是 user 中的id,因为它跟数据库的主键对应
order1. AFTER : 表示 SELECT LAST_INSERT_ID() 在insert执行之后执行,多用与自增主键
2. BEFORE : 表示 SELECT LAST_INSERT_ID() 在insert执行之前执行,这样的话就拿不到主键了,这种适合那种主键不是自增的类型
resultType主键类型

trim
一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。
主要属性:

属性说明
prefix给sql语句拼接的前缀
suffix给sql语句拼接的后缀
prefixesToOverride去除sql语句前面的关键字或者字符,该关键字或者字符由prefixesToOverride属性指定,假设该属性指定为”AND”,当sql语句的开头为”AND”,trim标签将会去除该”AND”
suffixesToOverride去除sql语句后面的关键字或者字符,该关键字或者字符由suffixesToOverride属性指定

如上面代码最后拼出来的为:

   insert into user (username,password) values (#{username}, #{password})

可以看到password和#{password}后面的逗号被suffixOverrides去除了。而且前面分别加上了 “(” 和 “values (” 这个前缀,以及 “)” 这个后缀,如果password为空的话,就变成下面这样:

  insert into user (username) values (#{username})
3.update
  <!--更新用户信息-->
   <update id="update" parameterType="com.example.demo.pojo.User">
   	update user set
   	<if test="username != null">username = #{userName},</if>
   	<if test="password != null">password = #{password},</if>
   	<if test="status != null">status = #{status},</if>
   	updatedAt = #{updatedAt}
 	where _id = #{id}
   </update>
4.delete
  <!-- 根据id删除用户 -->
  <delete id="delete" parameterType="java.lang.Integer">
   delete from user where _id = #{id}
  </delete>
5.sql
  <!--将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的,如下:-->
  <sql id="update_set">
   username = #{userName},password = #{password}
  </sql>

  <update id="update" parameterType="com.example.demo.pojo.User">
   update user set
     <include refid="update_set"/>
   where _id = #{id}
  </update>
6.bind
  	<!--多用于使用 #{} 接收参数是的 模糊查询中,如下-->
  <select id="findByUserName" parameterType="java.lang.String" resultMap="BaseResultMap">
   <bind name="bindName" value="'%'+_parameter+'%'"/>
   select *
   from user
   where  username like #{bindName}
7.resultMap
  <!--  将查询返回的结果映射到一个结果集当中。--->
  <resultMap id="BaseResultMap" type="com.example.demo.pojo.User">
   <id column="_id" property="id" jdbcType="INTEGER"/>
   <result column="username" property="username" jdbcType="VARCHAR"/>
   <result column="password" property="password" jdbcType="VARCHAR"/>
   <result column="createdAt" property="createdAt" jdbcType="BIGINT"/>
   <result column="updatedAt" property="updatedAt" jdbcType="BIGINT"/>
   <result column="status" property="status" jdbcType="INTEGER"/>
 </resultMap>

resultMap 属性:

属性说明
id唯一的标识 ,方便其他地方调用
type映射的pojo对象

< id >标签:

属性说明
column表的主键字段,或者可以为查询语句中的别名字段
jdbcType字段类型
property映射pojo对象的主键属性

< result >标签:

属性说明
column表的一个字段(可以为任意表的一个字段
jdbcType字段类型
property映射到pojo对象的一个属性(必须为type定义的pojo对象中的一个属性)

这里有一个注意点:映射的对象必须要有一个无参构造函数,否则会报错。这种情况多是个人需要,给映射的实体类添加了带参的构造函数(默认有一个无参构造函数,如果添加带参的构造函数,默认的将会失效),却忘记添加无参的构造函数

这里为了节省篇幅,只介绍基本使用, 以及 一对一,一对多、多对多等关系对象映射请点击这里 传送------>

四、传递、接收参数详解
1. 单个基本参数

  当mapper只有一个参数的时候,mybatis会直接取出参数值给mapper文件进行赋值如:#{id};

  public interface UserDao {
  	Integer findCount(String name)throws Exception;
  }

<select id="findCount" resultType="java.lang.Integer" parameterType="java.lang.String">
   <bind name="bindname" value="'%'+_parameter+'%'"/>
   select count(*)
   from user u
   where 1=1
   <if test="_parameter != null">
       and u.username like #{bindname}
       <!--  and u.username like #{name,jdbcType=VARCHAR} -->
   </if>
   and u.status != -1;
</select>

  上面代码功能是根据用户名模糊查询用户数量。参数类型为 String,返回的结果是整型,使用 Integer 接收。因为 #{} 是作为字符串没法拼接通配符 ‘%’,所以使用了 bind 标签进行拼接。

  这里提一下关于 #$
    #{} ${}二者区别最大在于:#{} 传入值时,sql解析时,参数是带引号的,而{}传入值,sql解析时,参数是不带引号的。注意,当只有一个参数,这个参数是基本类型而且没有使用@Param在Dao接口注解时,使用${}接收参数会报错!!!
    #{}: 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,一个 #{ } 被解析为一个参数占位符 。
     ${}: 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换。
传入一个不改变的字符串或者传入数据库字段(列名),例如要传入order by 后边的参数,这种情况下必须使用${}。

  注意:可以看到 bindif 标签上使用的是内置参数,_parameter 这是因为单个参数而且没有使用 @Param(可以看下一条 多个参数 注解的情况下,mybatis的这个标签,里面只对对象的属性或者map的内容进行判断。如果是单个的基本类型,并不满足以上条件,所以只能使用**_parameter** 。如果 < if test=“name != null”>就会报错!

   ${} 如果能不用最好不要使用,所以一般都是使用 #{} 接收参数,这里只有一个参数,直接 #{name} 接收就好,这里 #{name} 可以任意名称的 ,#{namename} , #{n123} 都可以。这里我还添加了 jdbcType Mybatis明文建议在映射字段数据时需要将 JdbcType 属性加上。这样相对来说是比较安全的。
java类型对应数据库类型

JDBC TypeJava Type
CHARString
VARCHARString
LONGVARCHARString
NUMERICjava.math.BigDecimal
DECIMALjava.math.BigDecimal
BITboolean
BOOLEANboolean
TINYINTbyte
SMALLINTshort
INTEGERINTEGER
BIGINTlong
REALfloat
FLOATdouble
DOUBLEdouble
BINARYbyte[]
VARBINARYbyte[]
LONGVARBINARYbyte[]
DATEjava.sql.Date
TIMEjava.sql.Time
TIMESTAMPjava.sql.Timestamp
CLOBClob
BLOBBlobl
ARRAYArray

2. 多个基本参数

1). 使用@Param 注解
   @Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中

  User updateById(@Param("userId") Integer id,@Param("username") String name ) throws Exception;

  <select id="updateById"  resultMap="BaseResultMap">
   	update user set 
     <if test="username!= null">
   	username= #{username}
   	</if>
     <if test="userId != null">
   	where _id = #{userId}
   </if>
  </select>

   这里直接可以拿到参数了 < if test=“username!= null”>,不需要再使用 _parameter 。#{userId} 对应 @Param(“userId”) , #{username} 对应 @Param(“username”),这样就可以做到多个参数传递了。

2). 使用 Map

  <!-- map.put("username",''myName"); 
  	   map.put("userId",12); -->
  User updateById(Map< String,Object> map) throws Exception;
  
  <select id="updateById"  parameterType="java.util.Map"  resultMap="BaseResultMap">
   	update user set 
     <if test="username!= null">
   	username= #{username}
   	</if>
     <if test="userId != null">
   	where _id = #{userId}
   </if>
  </select>

   当使用map时,map的键值 key 对应 #{key} 中的参数名称。

3. 对象参数
  Integer update(User user)throws Exception;//参数为对象	

  <update id="update" parameterType="com.example.demo.pojo.User">
   	update user set
  	<if test="username != null">username = #{userName},</if>
   	<if test="password != null">password = #{password},</if>
  	<if test="status != null">status = #{status},</if>
 	updatedAt = #{updatedAt }
   	where _id = #{id}
  </update>

    参数比较多的时候,一般都是封装成对象来进行参数传递,比如在往数据库插入数据或者更新数据的时候。 parameterType 此时指向对象(包路径必须,否则会报错找不到,可以在配置文件里设置别名,这样就可以不需要写路径,直接写别名即可,配置文件可以 点击这里直达–>)
    下面是对应的实体类

  public class User {
  	private String username;
  	private String password;
  	private Integer id;
  	private Long updatedAt;
  	private Long createdAt;
  	private Integer status;
  	
  	getter and setter ........
  }

    如果有多个对象类型参数,可以考虑再封装一层,或者通过 @Param 注解,如下

  List<User> select(@Param("user")User user,@Param("page")Page page);
  
    <select id="findByUserName" parameterType="java.lang.String" resultMap="BaseResultMap">
 	  select * from user 
 	  where status != -1
   	<if test="user.name != null">
       and username = #{user.name ,jdbcType=VARCHAR}
   	</if>
      limit #{page.offset}, #{page.limit}
    通过 @Param 就可以直接拿到参数了,而不需要 _parameter 。
好了,基本的操作如上,已经比较全了。如果有什么错误的地方,还望各位前辈海涵,多多指点,本人会一一答复并修改。
  • 11
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值