Mybatis集合用法 以及@param参数的原理

Mybatis集合用法 以及@param参数的原理

需求: 批量查询多个数据

难点: 如果使用#{集合}获取的是集合对象的整体.查询无效.
    思路: 将数组拆分为单个数据. 可以通过遍历的方式操作
    语法: mybatis为了参数取值方便,特意封装了遍历的标签 foreach
    关于标签参数说明:
        <foreach collection=""></foreach>
        1.如果传递的参数是数组,     则collection="array"
        2.如果传递的参数是list集合, 则collection="list"
        3.如果传递的参数是Map集合,  则collection="map中的key"

    标签属性说明:
        1.collection 集合的名称
        2.item 每次遍历的数据的形参变量
        3.open 循环的开始标签
        4.close 循环的结束标签
        5.index 循环遍历下标 一般不用
        6.separator 循环遍历的分割符

以数组方式传递

开启测试类:

@Test
    public void findByIds() {
          
   
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
        //封装为数组遍历查询
        int[] ids = {
          
   12,14,15,23,34,45,56,56};
        //封装为list
        List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(13);
        list.add(15);
        list.add(23);
        //封装为map
        HashMap<String, List> map = new HashMap<>();
        map.put("myMap", list);
        List<DemoUser> users = mapper.findByIds(ids);
        System.out.println("users = " + users);
    }

sql配置:

<select id="findByIds" resultType="edu.cque.pojo.DemoUser">
        select id,name,age,sex from demo_user where id in
            <foreach collection="array" open="(" close=")"  item="id" separator=", ">
                #{
          
   id}
            </foreach>

    </select>

以list方式传递:

@Test
    public void findByIds() {
          
   
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
        //封装为数组遍历查询
        int[] ids = {
          
   12,14,15,23,34,45,56,56};
        //封装为list
        List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(13);
        list.add(15);
        list.add(23);
        //封装为map
        HashMap<String, List> map = new HashMap<>();
        map.put("myMap", list);
        List<DemoUser> users = mapper.findByIds(list);
        System.out.println("users = " + users);
    }

接口方法:

List<DemoUser> findByIds(List list);

sql配置:

<select id="findByIds" resultType="edu.cque.pojo.DemoUser">
        select id,name,age,sex from demo_user where id in
            <foreach collection="list" open="(" close=")"  item="id" separator=", ">
                #{
          
   id}
            </foreach>

    </select>

运行结果:

以map方式

@Test
    public void findByIds() {
          
   
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
        //封装为数组遍历查询
        int[] ids = {
          
   12,14,15,23,34,45,56,56};
        //封装为list
        List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(13);
        list.add(15);
        list.add(23);
        //封装为map
        HashMap<String, List> map = new HashMap<>();
        map.put("myMap", list);
        List<DemoUser> users = mapper.findByIds(map);
        System.out.println("users = " + users);
    }

接口方法:

List<DemoUser> findByIds(Map map);

SQL配置: 注意这里collection中的取值是map中存入的key

<select id="findByIds" resultType="edu.cque.pojo.DemoUser">
        select id,name,age,sex from demo_user where id in
            <foreach collection="myMap" open="(" close=")"  item="id" separator=", ">
                #{
          
   id}
            </foreach>

    </select>

我们可以看到,三种不同的方式封装传递的数据,所调用接口方法对应的SQL配置中,只有collection的取值发生了改变.那有没有一种方式让我们的collection取值都是固定不变的呢?

答案是当然有的,当我们在定义接口中的抽象方法的时候,方法里面的参数前面如果加上@param注解,则就可以为当前需要传递的对象进行一层封装,封装为map集合的方式,key为@param的参数,value为@param参数后面的引用变量,在sql配置标签中,则通过这里的key来拿到数据. 下面我们来实战一下

用@param封装的list

@Test
    public void findByIds() {
          
   
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
        //封装为数组遍历查询
        int[] ids = {
          
   12,14,15,23,34,45,56,56};
        //封装为list
        List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(13);
        list.add(15);
        list.add(23);
        //封装为map
        HashMap<String, List> map = new HashMap<>();
        map.put("myMap", list);
        List<DemoUser> users = mapper.findByIds(list);
        System.out.println("users = " + users);
    }

接口方法: 这里我们给list进行了封装,后面取数据的时候用的就是myList了

List<DemoUser> findByIds(@Param("myList") List list);

sql配置:

select id,name,age,sex from demo_user where id in
            <foreach collection="myList" open="(" close=")"  item="id" separator=", ">
                #{id}
            </foreach>

    </select>

运行结果:

看到这里,有人可能已经想到了,数组方式和list方式传递数据,和以map方式传递数据好像非常的类似,其实就是在数组或list方式的基础之上用@param进行封装的话,其效果和直接用map形式原理是一样的. 那又有人会想到,如果我们再在map基础之前再封装一层@param注解会是怎样的结果,又应该如何取数据使用呢?

用@param方式封装的map

@Test
    public void findByIds() {
          
   
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
        //封装为数组遍历查询
        int[] ids = {
          
   12,14,15,23,34,45,56,56};
        //封装为list
        List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(13);
        list.add(15);
        list.add(23);
        //封装为map
        HashMap<String, List> map = new HashMap<>();
        map.put("myMap", list);
        List<DemoUser> users = mapper.findByIds(map);
        System.out.println("users = " + users);
    }

接口方法:

List<DemoUser> findByIds(@Param("myselfMap") Map map);

sql配置: 可以看到,现在使用collection取数据的话,没有之前那么好拿了,因为map被@param封装之后,就会变成<“myselfMap”,<“myMap”,list>>这种形式,取数据的话,可以先拿外层再拿里层.

至于这么做可能会感觉多此一举,好好的map封装了不是更加的麻烦了吗? 我之所以这么做,只是想让大家更清楚的知道@param是如何对数据进行封装的,掌握真正的核心原理.

<select id="findByIds" resultType="edu.cque.pojo.DemoUser">
        select id,name,age,sex from demo_user where id in
            <foreach collection="myselfMap.myMap" open="(" close=")"  item="id" separator=", ">
                #{
          
   id}
            </foreach>

    </select>

运行结果:

经验分享 程序员 微信小程序 职场和发展