目录

前言

一、动态SQL—if标签

1. 持久层添加用户通用查询方法

2. 映射文件添加相关标签

3. 测试类新建测试方法

4. 运行结果

二、动态SQL—where标签

1. 映射文件添加相关标签

2. 测试类新建测试方法

3. 运行结果

三、动态SQL—set标签

1. 持久层添加用户更新方法

2. 映射文件添加相关标签

3. 测试类新建测试方法

4. 运行结果

四、动态SQL—choose和wen和otherwise标签

1. 持久层添加用户通用查询方法

2. 映射文件添加相关标签

3. 测试类新建测试方法

4. 运行结果

五、动态SQL—foreach标签

1. 遍历数组

(1)持久层添加用户批量删除方法

(2)映射文件添加相关标签

(3)测试类新建测试方法

(4)运行结果

2. 遍历List

(1)持久层添加用户批量增加方法

(2)映射文件添加相关标签

(3)测试类新建测试方法

(4)运行结果

3. 遍历Map

(1)持久层添加多条件查询方法

(2)映射文件添加相关标签

(3)测试类新建测试方法

(4)运行结果

后言—-查错


前言

由于这是动态SQL,和先前得有些不一样,这里我们新建一个持久层接口UserMapper2和Mybatis映射文件UserMapper2.xml,测试类TestUserMapper2

持久层接口UserMapper2

package com.mybatisstudy.mapper;import com.mybatisstudy.pojo.User;public interface UserMapper2 {    }

Mybatis映射文件UserMapper2.xml

测试类TestUserMapper2

import com.mybatisstudy.mapper.UserMapper2;import com.mybatisstudy.pojo.User;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.After;import org.junit.Before;import org.junit.Test;import java.io.InputStream;public class TestUserMapper2 {    InputStream is = null;    SqlSession session = null;    UserMapper2 userMapper2 = null;    //前置方法,不必重复代码    @Before    public void before() throws Exception {        System.out.println("前置方法执行·············");        // (1)读取核心配置文件        is = Resources.getResourceAsStream("SqlMapConfig.xml");        // (2)创建SqlSessionFactoryBuilder对象        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();        // (3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象        SqlSessionFactory factory = builder.build(is);        // (4)SqlSessionFactory对象获取SqlSession对象        session = factory.openSession();        // (5)SqlSession对象获取代理对象        userMapper2 = session.getMapper(UserMapper2.class);    }    //后置方法,释放资源    @After    public void after() throws Exception {        System.out.println("后置方法执行·············");        session.close();        is.close();    }}

一、动态SQL—if标签

一个查询的方法的Sql语句不一定是固定的。比如电商网站的查询商品,用户使用不同条件查询,Sql语句就会添加不同的查询条件。此时就需要在方法中使用动态Sql语句。

标签内的Sql片段在满足条件后才会添加,用法为: 。例如:根据不同条件查询用户:

1. 持久层添加用户通用查询方法

// 用户通用查询    List findByCondition(User user);

2. 映射文件添加相关标签

            select * from user where 1 = 1                    and username like #{username}                            and sex = #{sex}                            and address = #{address}            

这里肯定就会有读者会问where 后面为什么要加1 = 1,因为单单使用if标签的话,第一个条件是不用 and 关键字的,而后续的条件是需要加 and 关键字的。但是用户添加条件是随机的,没办法判断哪一个是第一个条件,因此在这里先添加1 = 1,就无需考虑后续的条件是否是第一个条件啦,但是后面还有更好的办法解决这个问题,在这里只是可以用这个方法解决目前的问题。

3. 测试类新建测试方法

// 测试通用查询方法    @Test    public void testFindByCondition(){        User user = new User();        System.out.println("----------没有限制条件查询---------");        List users = userMapper2.findByCondition(user);        users.forEach(System.out::println);        System.out.println("----------用户名带有name限制条件查询---------");        user.setUsername("%name%");        List users1 = userMapper2.findByCondition(user);        users1.forEach(System.out::println);        System.out.println("----------姓名带有name和性别是man限制条件查询---------");        user.setSex("woman");        List users3 = userMapper2.findByCondition(user);        users3.forEach(System.out::println);    }

4. 运行结果

  1. if中的条件不能使用&&/||,而应该使用and/or

  2. if中的条件可以直接通过属性名获取参数POJO的属性值,并且该值可以调用方法。

二、动态SQL—where标签

OK,上述的问题的彩蛋来了,就是这个where标签,

可以代替sql中的where 1=1 和第一个and,更符合程序员的开发习惯,使用 后的映射文件如下:

1. 映射文件添加相关标签

            select * from user                                    username like #{username}                                        and sex = #{sex}                                        and address = #{address}                        

2. 测试类新建测试方法

这里不用新增,直接测试即可

3. 运行结果

因此我们以后就不用添加那个什么1 = 1了

三、动态SQL—set标签

标签用在update语句中。借助 ,可以只对有具体值的字段进行更新。 会自动添加set关键字,并去掉最后一个if语句中多余的逗号。

1. 持久层添加用户更新方法

// 更新用户    void update(User user);

2. 映射文件添加相关标签

            update user                                    username = #{username}                                        and sex = #{sex}                                        and address = #{address}                                        id = #{id}            

3. 测试类新建测试方法

// 测试更新用户方法    @Test    public void testUpdate(){        User user = new User();        user.setId(4);        user.setUsername("man4");        userMapper2.update(user);        session.commit();    }

4. 运行结果

这里想整一个效果图,但是没想到帧率不够,最后居然绿屏了,但是不影响我们继续学习哈哈哈,理解到位即可害嗨嗨

四、动态SQL—choose和wen和otherwise标签

这些标签表示多条件分支,类似JAVA中的 switch…case 类似switch 类似 case 类似 default ,用法如下:

1. 持久层添加用户通用查询方法

这里就沿用那个通用查询方法即可

2. 映射文件添加相关标签

            select * from user                                                        username like #{username}                                                    username = #{username}                                                    id = 1                                        

这段代码的含义就是当用户名的长度小于(不等于)5的时候,使用模糊查询,查询返回的是泛型为USer的List集合对象,list长度不定;当用户名大于等于5,小于10的时候,使用精确查询,查询指定用户名的用户,返回的是泛型为USer的List集合对象,list长度为1或者0;当用户名长度大于等于10的时候,返回的是id为1的用户

3. 测试类新建测试方法

// 测试通用查询方法——用户名    @Test    public void testFindByCondition1(){        User user = new User();        System.out.println("------------设用户名字长度为2------------");        user.setUsername("%on%");        List users = userMapper2.findByCondition(user);        users.forEach(System.out::println);        System.out.println("------------设用户名字长度为5------------");        user.setUsername("%lions%");        users = userMapper2.findByCondition(user);        users.forEach(System.out::println);        System.out.println("------------设用户名字长度为9------------");        user.setUsername("T_no_name");        users = userMapper2.findByCondition(user);        users.forEach(System.out::println);        System.out.println("------------设用户名字长度为10------------");        user.setUsername("dddddddddd");        users = userMapper2.findByCondition(user);        users.forEach(System.out::println);        System.out.println("------------设用户名字长度为12------------");        user.setUsername("programmer_1");        users = userMapper2.findByCondition(user);        users.forEach(System.out::println);    }

4. 运行结果

OK,其实从结果集和运行的SQL语句我们都可以得出,该映射文件的标签确实是验证了咱们刚刚的说法

五、动态SQL—foreach标签

类似JAVA中的for循环,可以遍历集合或数组。 有如

下属性:

  1. collection:遍历的对象类型
  2. open:开始的sql语句
  3. close:结束的sql语句
  4. separator:遍历每项间的分隔符
  5. item:表示本次遍历获取的元素,遍历ListSet、数组时表示每项元素,遍历map时表示键值对的值。
  6. index:遍历List、数组时表示遍历的索引,遍历map时表示键值对的键。

1. 遍历数组

(1)持久层添加用户批量删除方法

// 用户批量删除    void deleteBatch(int[] ids);

(2)映射文件添加相关标签

                delete from user                                    #{id}                        

其实这里对应的SQL语句就是:

delete from user in (” />

运行后,四和八对应的记录确实是被删除了

2. 遍历List

遍历ListSet的方法是一样的,我们使用 遍历List进行批量添加。

(1)持久层添加用户批量增加方法

// 批量增加用户    void insertBatch(List users);

(2)映射文件添加相关标签

            insert into user values                    (null,#{user.username},#{user.sex},#{user.address})            

这里对应的SQL语句则是:

insert into user values(null,username,sex,address)*N

N可以为大于或等于1的数

其中肯定会有人问到了,为什么id要为null,其实这里id是主键,我们建库建表的时候就已经设置了这里是自增字段,因此我们无需重复操作,如果设置有和表里面的id重复,说不定还会报错

(3)测试类新建测试方法

// 测试批量增加用户方法    @Test    public void testInsertBatch(){        List list = new ArrayList();        list.add(new User("man1","man","Beijing"));        list.add(new User("man1","man","Beijing"));        list.add(new User("man1","man","Beijing"));        list.add(new User("man1","man","Beijing"));        list.add(new User("man1","man","Beijing"));        list.add(new User("man1","man","Beijing"));        userMapper2.insertBatch(list);        session.commit();    }

(4)运行结果

运行前和运行后进行对比

OK,通过对比,确实是增加了相关记录,这里的id是因为我测试过很多次了,所以比较大,大家不用在意这些哈哈哈,侧面反映我是很认真在写的,期待小伙伴的支持

3. 遍历Map

下面我们使用 遍历Map进行多条件查询。

(1)持久层添加多条件查询方法

/**     * 多条件查询     * @param map 查询的键值对 键:属性名 值:属性值     * @return     */    List findUser(@Param("queryMap") Map map);

(2)映射文件添加相关标签

            select * from user                                    ${key} = #{value}                        

这里对应的代码段其实就是:

select * from user where (” />

执行方法,观察结果是否一致 (是的,确实一致),不一致怎么会放出来呢

OK,这里确实保持一致,动态查询就学到这里了,后续会继续更新相关内容滴,敬请关注! !!

后言—-查错

如果执行过程中有错误的话,不妨看看有没有导错包和导错类,下面就是上面用到相关的类用到的导包

持久层接口用到的包

package com.mybatisstudy.mapper;import com.mybatisstudy.pojo.User;import org.apache.ibatis.annotations.Param;import java.util.List;import java.util.Map;

测试类用到的包

import com.mybatisstudy.mapper.UserMapper2;import com.mybatisstudy.pojo.User;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.After;import org.junit.Before;import org.junit.Test;import java.io.InputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;