Mybatis动态SQL

MyBatis

Mybatis笔记连载上篇连接MyBatis缓存
Mybatis笔记连载下篇连接

动态SQL

动态SQL可以根据条件智能生成SQL语句。通过if,choose,when,otherwise,trim,where,set,foreach等标签,可组成比较灵活的sql语句。

较多例子,需要使用到sqlsession,写出一个可复用的getSession方法

  SqlSession getSession() throws IOException {
        String resource = "Mybatis/mybatis-config.xml";
        Reader reader = Resources.getResourceAsReader(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sqlSessionFactory.openSession();
        return session;
    }

一、if语句

<!--模糊搜索if语句-->
<select id="finduserbylikename1" parameterType="string" resultMap="userResult">
    select * from t_user where 1=1
    <if test="_parameter!=null and _parameter!=''">
        and name like #{_parameter}
    </if>
</select>
<select id="finduserbylikename2" parameterType="map" resultMap="userResult">
    <bind name="pattern" value="'%' + _parameter.name + '%'"/>
    select * from t_user where 1=1
    <if test="_parameter.name!=null and _parameter.name!=''">
        and name like #{pattern}
    </if>
</select>

以上例子是使用了if语句来使用模糊搜索,注意到有1=1的条件,是防止无传入条件时没有生成任何语句导致的where结尾造成的错误,当没有传入条件时默认查询全部。

_parameter这个属性,表示的是传入的参数,如果传入的参数有多个,如果是list那么使用_parameter.get(i)来获取参数,如果是map的参数有key值,可以使用_parameter.key来获取key对应的value参数。

在finduserbylikename1中使用的是String参数,传入参数只有一个,直接用_parameter来判断,如果是空就不需要增加语句,反之使用这个String参数来生成一个模糊查询语句。

在finduserbylikename2中使用的是Map参数,传入的参数可以为多个,_parameter.name相当于map.get("name")获得这里的value,来进行判断。如果是空就不需要增加语句,反之使用这个value来生成一个模糊查询语句。其中的bind属性是将传入的参数进行增强处理,这里的bind是将传入的name前面后加%号并起一个别名为pattern,这样在java程序中填写程序就不需要再加%号并且在下方使用这个参数时可以直接使用这个别名。

测试代码

    @Test
    public void likenameTest() throws IOException {
        SqlSession session = getSession();
        String stat = "test.mybatis.DBMapping.UserMapper.finduserbylikename1";
        List<User> users = session.selectList(stat,"%张%");
        for (User user : users) {
            System.out.println(user.toString());
        }
        stat = "test.mybatis.DBMapping.UserMapper.finduserbylikename2";
        Map<String,Object> map = new HashMap<>();
        map.put("name","张");
        users = session.selectList(stat,map);
        for (User user : users) {
            System.out.println(user.toString());
        }
    }

运行结果:
Id:1 Name:张三 Age:24 Money:666.66
Id:1 Name:张三 Age:24 Money:666.66

二、choose语句

这个语句相当于java中的switch语句。

<!--模糊搜索choose-->
<select id="findcard" parameterType="map" resultMap="cardResult">
    select * from card where 1=1
    <choose>
        <when test="_parameter.type=='city'">
            <bind name="city" value="'%' + _parameter.value + '%'"/>
            and city like #{city}
        </when>
        <when test="_parameter.type=='address'">
            <bind name="address" value="'%' + _parameter.value + '%'"/>
            and address like #{address}
        </when>
        <otherwise>
            <bind name="city" value="'%' + _parameter.city + '%'"/>
            <bind name="address" value="'%' + _parameter.address + '%'"/>
            and city like #{city} or address like #{address}
        </otherwise>
    </choose>
</select>
@Test
public void findcard() throws IOException {
    SqlSession session = getSession();
    String stat = "test.mybatis.DBMapping.UserMapper.findcard";
    Map map = new HashMap();
    map.put("value","city");
    map.put("type","city");
    List<Card> cards = session.selectList(stat,map);
    for (Card card : cards) {
        System.out.println(card.toString());
    }
    map = new HashMap();
    map.put("type","other");
    map.put("city","city");
    map.put("address","address");
    cards = session.selectList(stat,map);
    for (Card card : cards) {
        System.out.println(card.toString());
    }
}

这里根据使用的哪个查询来生成对应的代码在map中放置两个属性,一个type代表程序使用哪个类型来查询,一个value代表这个类型时使用的参数。

还有一种情况,就是有时候对对象的修改操作时,需要两个以上的条件来修改这个行,有时要根据id修改name,有时需要根据id修改age,有时要根据age和name来修改city。这个时候就要使用到trim。

  • prefix:在trime标签内为sql语句加上前缀。

  • suffix:在trime标签内为sql语句加上后缀。

  • suffixOverrides:指定去除多余的后缀内容。

  • prefixOverrides:指定去除多余的前缀内容。

<!--使用trim标签的choose-->
<select id="updatecard" parameterType="map" >
    update card
    <trim prefix="set" suffixOverrides=",">
        <if test="_parameter.cardNo!=null and _parameter.cardNo!=''">
            cardNo = #{cardNo},
        </if>
        <if test="_parameter.city!=null and _parameter.city!=''">
            city = #{city},
        </if>
    </trim>
    <trim prefix="where" prefixOverrides="and|or">
        <if test="_parameter.id!=null and _parameter.id!=''">
            and id = #{id}
        </if>
        <if test="_parameter.address!=null and _parameter.address!=''">
            and address = #{address}
        </if>
    </trim>
</select>

以上例子就是在update card后增加以set为前缀的判断修改参数是否为空来增加参数和去除尾巴多余的逗号,再增加以where为前缀的判断查询参数是否为空来增加参数和去除多余前缀and|or。

@Test
public void updatecard() throws IOException {
    SqlSession session = getSession();
    String stat = "test.mybatis.DBMapping.UserMapper.findcard";
    Map map = new HashMap();
    map.put("cradNo","cardNo1");
    map.put("city","city1");
    map.put("id",1);
    map.put("address","address");
    session.update(stat,map);
    session.commit();
    stat = "test.mybatis.DBMapping.UserMapper.findcard";
    map = new HashMap();
    map.put("type","address");
    map.put("value","address");
    List<Card> cards = session.selectList(stat,map);
    System.out.println("更改后通过查询\n");
    for (Card card : cards) {
        System.out.println(card.toString());
    }
}

执行更改后,再通过findcard进行查询输出。

三、foreach语句

有时候sql需要使用到in查询,例如

这个时候就需要使用到foreachh语句。

  • Item:表示集合中每一个元素进行迭代时的别名。
  • Index:指定一个名字,用于表示在迭代过程中每次迭代到的位置。
  • Open:表示该语句以什么开始。
  • Separator:表示在每次进行迭代之间以什么符号作为分隔符。
  • Close:表示以什么结束。
<select id="findcardbyuserids" parameterType="map" resultMap="userResult">
    select * from t_user where id in
    <foreach collection="ids" index="index" 
        item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

foreach中使用传进来的map类型的ids来进行迭代,使用index来代表迭代到的位置,使用item来代表单个元素的别名。在迭代开始时增加一个(,在结束时增加一个)。

@Test
public void foreachTest() throws IOException {
    SqlSession session = getSession();
    String stat = "test.mybatis.DBMapping.UserMapper.findcardbyuserids";
    List ids = new ArrayList();
    ids.add("1");
    ids.add("2");
    ids.add("3");
    Map map = new HashMap();
    map.put("ids",ids);
    List<User> users = session.selectList(stat,map);
    for (User user : users) {
        System.out.println(user.toString());
    }
}

传入ids后,生成的语句就是

select * from t_user id in(1,2,3)

执行结果

Id:1 Name:张三 Age:24 Money:666.66

Id:2 Name:李四 Age:25 Money:888.88

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

推荐阅读更多精彩内容

  • MyBatis 动态SQL 内容 Mybatis动态SQL在XML中支持的几种标签: if chose trim、...
    lihongyan阅读 8,374评论 1 10
  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,524评论 0 4
  • Mybatis学习 mybatis http://www.mybatis.org/mybatis-3/zh/ind...
    墙上藤蔓阅读 761评论 3 2
  • 、 、 、 :trim标签主要就是标记的作用,可以去掉if条件不满足时多余的and或者or或者,等等,和set标...
    小沙鹰168阅读 1,992评论 0 0
  • MyBatis动态SQL语句 MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类...
    木易林1阅读 615评论 0 1