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

一、在mapper中几个常用元素

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

二 、基本结构

  
  
  
  	....
  
namespace :是用于绑定Dao接口的,即面向接口编程。当你的namespace绑定接口后,你可以不用写接口实现类,mybatis会通过该绑定自动帮你找到对应要执行的SQL语句.注意这里需要完整的路径,不要写错,不然会报找不到的错误。

三、常用标签元素使用

1.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 这是暗示驱动程序每次批量返回的结果行数。默认不设置(驱动自行处理)。
statementType STA TEMENT,PREPARED 或 CALLABLE 的一种。这会让 MyBatis 使用选择使用 Statement,PreparedStatement 或 CallableStatement。默认值:PREPARED。
resultSetType FORWARD_ONLY|SCROLL_SENSITIVE|SCROLL_INSENSITIVE 中的一种。默认是不设置(驱动自行处理)。
2.insert
  
  
  	
   
       SELECT LAST_INSERT_ID() as id
   
   insert into user
   
       
           username,
       
       
           password,
       
   
   
       
           #{username},
       
       
           #{password},
       
   

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

属性 说明
keyProperty 对应的model中的主键的属性名,这里是 user 中的id,因为它跟数据库的主键对应
order 1. 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 user set
   	username = #{userName},
   	password = #{password},
   	status = #{status},
   	updatedAt = #{updatedAt}
 	where _id = #{id}
   
4.delete
  
  
   delete from user where _id = #{id}
  
5.sql
  
  
   username = #{userName},password = #{password}
  

  
   update user set
     
   where _id = #{id}
  
6.bind
  	
  
   
   select count(*)
   from user u
   where 1=1
   
       and u.username like #{bindname}
       
   
   and u.status != -1;

  上面代码功能是根据用户名模糊查询用户数量。参数类型为 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 Type Java Type
CHAR String
VARCHAR String
LONGVARCHAR String
NUMERIC java.math.BigDecimal
DECIMAL java.math.BigDecimal
BIT boolean
BOOLEAN boolean
TINYINT byte
SMALLINT short
INTEGER INTEGER
BIGINT long
REAL float
FLOAT double
DOUBLE double
BINARY byte[]
VARBINARY byte[]
LONGVARBINARY byte[]
DATE java.sql.Date
TIME java.sql.Time
TIMESTAMP java.sql.Timestamp
CLOB Clob
BLOB Blobl
ARRAY Array

2. 多个基本参数

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

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

  

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

2). 使用 Map

  
  User updateById(Map< String,Object> map) throws Exception;
  
  

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

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

  
   	update user set
  	username = #{userName},
   	password = #{password},
  	status = #{status},
 	updatedAt = #{updatedAt }
   	where _id = #{id}
  

    参数比较多的时候,一般都是封装成对象来进行参数传递,比如在往数据库插入数据或者更新数据的时候。 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 select(@Param("user")User user,@Param("page")Page page);