Mybatis实战2:标签详解

image.png

一、select标签

1.标签属性

  • id 唯一的名称,对应dao中mapper的接口名称
  • paramterType 定义传入的参数类型
  • resultType 返回数据类型对应实体类
  • resultMap 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用
  • flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false
  • useCache 将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:true
  • timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动),若设置10,则表示10秒内数据库没有返回结果就抛出异常
  • fetchSize 这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动),比如设置为20,而你要查询的总记录是100条,驱动会每次批量查询20条,共查询5次,myabtis会将这5次结果聚合一起返回100条。注意Mysql是不支持fetchSize的
  • statementType STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED
  • resultSetType FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)
  • databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
  • resultOrdered 这个设置仅针对嵌套结果 select 语句适用:如果为true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至导致内存不够用。默认值:false。
  • resultSets 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。

2.查询示例

1.简单查询

mapper接口

    // 根据 id 获得数据库中的 username 字段的值
    String getUserNameById(Integer id);

mapper.xml

<!-- 
        指定 resultType 返回值类型时 String 类型的,
        string 在这里是一个别名,代表的是 java.lang.String 

        对于引用数据类型,都是将大写字母转小写,比如 HashMap 对应的别名是 'hashmap'
        基本数据类型考虑到重复的问题,会在其前面加上 '_',比如 byte 对应的别名是 '_byte'
    -->
    <select id="getUserNameById" resultType="java.lang.String">
    select user_name from user_info where id = #{id}
  </select>
2.查询返回JavaBean

返回Java实体类可以使用resultType属性
多个查询条件,可以使用@Param 来指定
mapper接口

// 多个查询条件,可以使用
UserInfo selectByNamePwd(@Param("userName") String userName, @Param("password") String password);
  <!--通过用户名和密码查询-->
  <select id="selectByNamePwd" resultType="com.gqlofe.userinfo.bean.entity.UserInfo">
    select
    <include refid="Base_Column_List" />
    from user_info
    where user_name = #{userName} and password = #{password}
  </select>
3.返回list类型

mapper方法返回类型是List,则查询的结果就是List,xml中resultType指定的是返回List的元素的类型

List<UserInfo> selectAll();
  <select id="selectAll" resultType="com.gqlofe.userinfo.bean.entity.UserInfo">
    select * from user_info
  </select>
4.返回Map类型
  • 如果查询的结果是一条,我们可以把查询的数据以{表字段名, 对应的值}方式存入到Map中
    MyBatis 还支持将查询的数据封装成 Map。其中key是数据库表字段名,即是下划线格式
    //  根据 id 查询信息,并把结果信息封装成 Map
    Map<String, Object> getMapById(Integer id);
  <select id="getMapById" resultType="hashmap">
    select * from user_info where id = #{id}
  </select>
  • 如果查询的结果是多条数据,我们也可以把查询的数据以{表中某一字段名, JavaBean}方式来封装成Map
    @MapKey 中的值表示用数据库中的哪个字段名作 key
    @MapKey("id")
    Map<Integer, UserInfo> getAllUserInfoAsMap();
  <!--本可以使用resultType="com.gqlofe.userinfo.bean.entity.UserInfo"-->
  <!--但由于数据库字段名和实体类属性名不一致,所以使用resultMap,表示map的value的类型-->
  <select id="getAllUserInfoAsMap" resultMap="BaseResultMap">
    select * from user_info
  </select>

二、insert,update,delete标签

属性名称 释义 示例
id 唯一的名称,对应dao中mapper的接口名称 selectById
paramterType 定义传入的参数类型 long
flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false fasle
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动),若设置10,则表示10秒内数据库没有返回结果就抛出异常 10
statementType STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED PREPARED
useGeneratedKeys (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server这样的关系数据库管理系统的自动递增字段, oracle使用序列是不支持的,通过selectKey可以返回主键),默认值:false。 true
keyProperty (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 id
keyColumn (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 id
databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。

三、sql标签

定义一些常用的sql语句片段

<sql id="selectParam">
    id, username, password, sex, birthday, address
</sql>

四、include 标签

引用其他的常量,通常和sql一起使用

<select>
    select <include refid="selectParam"></include>
    from user_info
</select>

五、if 标签

基本都是用来判断值是否为空,注意Integer的判断,mybatis会默认把0变成 ‘’

<if test="item != null and item != ''"></if>

<!-- 如果是Integer类型的需要把and后面去掉或是加上or-->
<if test="item != null"></if>
<if test="item != null and item != '' or item == 0"></if>

六、别名typeAliases标签

经常使用的类型可以定义别名,方便使用,mybatis也注册了很多别名方便我们使用,详情见底部

<typeAliases>
     <typeAlias type="com.gqlofe.userinfo.bean.entity.UserInfo" alias="User"/>
</typeAliases>

七、where标签

当使用if标签进行条件判断时有可能第一个条件不满足,会导致where语句中多一个and 或者or,如下:

  <select id="selectByNamePwd" resultType="com.gqlofe.userinfo.bean.entity.UserInfo">
    select
    <include refid="Base_Column_List" />
    from user_info
    where
    <if test="userName != null">
      user_name = #{userName}
    </if>
    <if test="password != null">
      and password = #{password}
    </if>
  </select>

如果userName= null,则sql语句就变成

select * from user_info where and password = #{password}

显然有问题,where标签可以去除where语句中的第一个and 或 or。
用法:

  <select id="selectByNamePwd" resultType="com.gqlofe.userinfo.bean.entity.UserInfo">
    select
    <include refid="Base_Column_List" />
    from user_info
    <where>
      <if test="userName != null">
        user_name = #{userName}
      </if>
      <if test="password != null">
        and password = #{password}
      </if>
    </where>
  </select>

八、set标签

update语句中,set标签可以去除多余的逗号,用法:

<update id="updateByPrimaryKeySelective" parameterType="com.gqlofe.userinfo.bean.entity.UserInfo">
    update user_info
    <set>
      <if test="userName != null">
        user_name = #{userName,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        password = #{password,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        phone = #{phone,jdbcType=VARCHAR},
      </if>
      <if test="icon != null">
        icon = #{icon,jdbcType=VARCHAR},
      </if>
      <if test="sex != null">
        sex = #{sex,jdbcType=INTEGER},
      </if>
      <if test="age != null">
        age = #{age,jdbcType=INTEGER},
      </if>
      <if test="birthday != null">
        birthday = #{birthday,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=BIGINT},
      </if>
      <if test="updateTime != null">
        update_time = #{updateTime,jdbcType=BIGINT},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>

九、trim标签

where标签只能去除第一个and或or,不够灵活,trim标签功能更加强大。
trim标签的属性如下:

  • prefix 在trim标签内容前面加上前缀
  • suffix 在trim标签内容后面加上后缀
  • prefixOverrides 移除前缀内容。即 属性会忽略通过管道分隔的文本序列,多个忽略序列用 “|” 隔开。它带来的结果就是所有在 prefixOverrides 属性中指定的内容将被移除。
  • suffixOverrides 移除前缀内容。
<insert id="insertSelective" parameterType="UserInfo" useGeneratedKeys="true" keyProperty="id">
    insert into user_info
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="userName != null">
        user_name,
      </if>
      <if test="password != null">
        password,
      </if>
      <if test="phone != null">
        phone,
      </if>
      <if test="icon != null">
        icon,
      </if>
      <if test="sex != null">
        sex,
      </if>
      <if test="age != null">
        age,
      </if>
      <if test="birthday != null">
        birthday,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="updateTime != null">
        update_time,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="userName != null">
        #{userName,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        #{password,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        #{phone,jdbcType=VARCHAR},
      </if>
      <if test="icon != null">
        #{icon,jdbcType=VARCHAR},
      </if>
      <if test="sex != null">
        #{sex,jdbcType=INTEGER},
      </if>
      <if test="age != null">
        #{age,jdbcType=INTEGER},
      </if>
      <if test="birthday != null">
        #{birthday,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=BIGINT},
      </if>
      <if test="updateTime != null">
        #{updateTime,jdbcType=BIGINT},
      </if>
    </trim>
  </insert>

十、foreach标签

foreach元素的属性主要有item,index,collection,open,separator,close.

  • collection 要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:如果User有属性List ids。入参是User对象,那么这个collection = "ids".如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id",必填
  • item 合中元素迭代时的别名,必选
  • index 在list和数组中,index是元素的序号,在map中,index是元素的key,可选
  • open foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。可选
  • separator 元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样,可选。
  • close foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。可选
<select id="countByUserList" resultType="_int" parameterType="list">
select count(*) from user_info
  <where>
    id in
    <foreach item="item" collection="list" separator="," open="(" close=")" index="">
      #{item.id, jdbcType=NUMERIC}
    </foreach>
  </where>
</select>

<select id="dynamicForeach2Test" resultType="Blog">
     select * from t_blog where id in
     <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
          #{item}
     </foreach>
</select>

十一、choose,when,otherwise标签

功能有点类似于Java中的 swicth - case - default

<select id="getUser" resultType="com.cat.pojo.User">
  SELECT * FROM user 
  <where>
  <choose>
    <when test="id != null and test.trim() != '' ">
      id = #{id}
    </when> 
    <when test="name != null and name.trim() != '' ">
      name = #{name}
    </when> 
    <otherwise>
      age = 17  
    </otherwise>
  </choose>
</where>
</select>

七、resultMap标签

在平时的开发中,我们没有办法一定能保证表中的字段名和表对应实体类的属性名称是完全相同的,resultMap可以解决表字段和实体属性名不一致的问题
表结构

CREATE TABLE `user_info` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名',
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密码',
  `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机',
  `icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '头像链接地址',
  `sex` int(5) NOT NULL DEFAULT '3' COMMENT '性别: 1 男,2 女, 3 保密',
  `age` int(5) NOT NULL DEFAULT '0' COMMENT '年龄',
  `birthday` bigint(15) DEFAULT '0' COMMENT '出生年月',
  `create_time` bigint(15) NOT NULL DEFAULT '0' COMMENT '创建时间',
  `update_time` bigint(15) NOT NULL DEFAULT '0' COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `index_name` (`user_name`) USING BTREE COMMENT '用户名唯一索引',
  KEY `index_phone` (`phone`) USING BTREE COMMENT '手机号索引'
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='用户表';

实体类

@Data
@Accessors(chain = true)
public class UserInfo implements Serializable {
    // 用户id
    private Integer id;
    // 用户名
    private String userName;
    // 密码
    private String password;
    // 手机
    private String phone;
    // 头像链接地址
    private String icon;
    // 性别: 1 男,2 女, 3 保密
    private Integer sex;
    // 年龄
    private Integer age;
    // 出生年月
    private Long birthday;
    // 创建时间
    private Long createTime;
    // 更新时间
    private Long updateTime;
    private static final long serialVersionUID = 1L;
}

可以看出数据库字段一般是以下划线的格式,而Java实体类是以驼峰格式,为了保证能正确映射,就需要使用resultMap标签

 <resultMap id="BaseResultMap" type="com.gqlofe.userinfo.bean.entity.UserInfo">
   <id column="id" jdbcType="INTEGER" property="id" />
   <result column="user_name" jdbcType="VARCHAR" property="userName" />
   <result column="password" jdbcType="VARCHAR" property="password" />
   <result column="phone" jdbcType="VARCHAR" property="phone" />
   <result column="icon" jdbcType="VARCHAR" property="icon" />
   <result column="sex" jdbcType="INTEGER" property="sex" />
   <result column="age" jdbcType="INTEGER" property="age" />
   <result column="birthday" jdbcType="BIGINT" property="birthday" />
   <result column="create_time" jdbcType="BIGINT" property="createTime" />
   <result column="update_time" jdbcType="BIGINT" property="updateTime" />
 </resultMap>

 <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
   select 
   <include refid="Base_Column_List" />
   from user_info
   where id = #{id,jdbcType=INTEGER}
 </select>

使用resultMap将数据库字段名和Java实体类属性名一一映射,在查询sql中使用resultMap=BaseResultMap,其中 BaseResultMap 是resultMap的id。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,454评论 0 4
  • 前言 MyBatis是一个优秀的持久层ORM框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL...
    AI乔治阅读 637评论 0 5
  • mybatis中的sqlSession是线程安全的吗? 链接:https://blog.csdn.net/qq_3...
    刘小刀tina阅读 2,062评论 0 3
  • 百天培训如期至, 未来前翘首企盼。 日思夜想这天来, 果真如期已来到。 培训结果千千万, 却道不尽伤离别。 一别不...
    毛毛静丫阅读 151评论 2 3
  • 用柔软的舌头 捅破 天。
    风雨年轮阅读 100评论 0 3