Mybatis动态SQL

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
# java  Mybatis 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×