zoukankan      html  css  js  c++  java
  • Mybatis+MySQL动态分页查询

    https://blog.csdn.net/qq_34137397/article/details/63289621

    mybatis有两种分页方法

    1、内存分页,也就是假分页。本质是查出所有的数据然后根据游标的方式,截取需要的记录。如果数据量大,开销大和内存溢出。

    第二中是,真正的物理分页

    还有一种是使用分页拦截器实现的

    常见的数据分页有哪几种实现??基于数组的分页实现?基于sql语句的分页实现?还是通过拦截器进行数据分页功能?还是通过RowBounds参数进行物理分页?几种都是常用的分页实现原理

    一.借助数组进行分页

    原理:进行数据库查询操作时,获取到数据库中所有满足条件的记录,保存在应用的临时数组中,再通过List的subList方法,获取到满足条件的所有记录。

    二.借助Sql语句进行分页,物理分页

    实现:通过sql语句实现分页也是非常简单的,只是需要改变我们查询的语句就能实现了,即在sql语句后面添加limit分页语句。
    
    首先还是在StudentMapper接口中添加sql语句查询的方法,如下:
    
    List<Student> queryStudentsBySql(Map<String,Object> data);
    然后在StudentMapper.xml文件中编写sql语句通过limiy关键字进行分页:
    
     <select id="queryStudentsBySql" parameterType="map" resultMap="studentmapper">
            select * from student limit #{currIndex} , #{pageSize}
    </select>
    接下来还是在IStuService接口中定义方法,并且在StuServiceIml中对sql分页实现。
    
    List<Student> queryStudentsBySql(int currPage, int pageSize);
     @Override
        public List<Student> queryStudentsBySql(int currPage, int pageSize) {
            Map<String, Object> data = new HashedMap();
            data.put("currIndex", (currPage-1)*pageSize);
            data.put("pageSize", pageSize);
            return studentMapper.queryStudentsBySql(data);
        }
    sql分页语句如下:select * from table limit index, pageSize;
    四.RowBounds实现分页
    
    原理:通过RowBounds实现分页和通过数组方式分页原理差不多,都是一次获取所有符合条件的数据,然后在内存中对大数据进行操作,实现分页效果。只是数组分页需要我们自己去实现分页逻辑,这里更加简化而已。
    
    存在问题:一次性从数据库获取的数据可能会很多,对内存的消耗很大,可能导师性能变差,甚至引发内存溢出。
    
    适用场景:在数据量很大的情况下,建议还是适用拦截器实现分页效果。RowBounds建议在数据量相对较小的情况下使用。
    
    简单介绍:这是代码实现上最简单的一种分页方式,只需要在dao层接口中要实现分页的方法中加入RowBounds参数,然后在service层通过offset(从第几行开始读取数据,默认值为0)和limit(要显示的记录条数,默认为java允许的最大整数:2147483647)两个参数构建出RowBounds对象,在调用dao层方法的时,将构造好的RowBounds传进去就能轻松实现分页效果了。
    
    具体操作如下:
    
    dao层接口方法:
    
    //加入RowBounds参数
    public List<UserBean> queryUsersByPage(String userName, RowBounds rowBounds);
    
    然后在service层构建RowBounds,调用dao层方法:
    
      @Override
        @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.SUPPORTS)
        public List<RoleBean> queryRolesByPage(String roleName, int start, int limit) {
            return roleDao.queryRolesByPage(roleName, new RowBounds(start, limit));
        }
    
    RowBounds就是一个封装了offset和limit简单类,如下所示:
    
    public class RowBounds {
        public static final int NO_ROW_OFFSET = 0;
        public static final int NO_ROW_LIMIT = 2147483647;
        public static final RowBounds DEFAULT = new RowBounds();
        private int offset;
        private int limit;
    
        public RowBounds() {
            this.offset = 0;
            this.limit = 2147483647;
        }
    
        public RowBounds(int offset, int limit) {
            this.offset = offset;
            this.limit = limit;
        }
    
        public int getOffset() {
            return this.offset;
        }
    
        public int getLimit() {
            return this.limit;
        }
    }
    
    只需要这两步操作,就能轻松实现分页效果了,是不是很神奇。但却不简单,内部是怎么实现的??给大家提供一个简单的思路:RowBounds分页简单原理
    
    结论:从上面四种sql分页的实现方式可以看出,通过RowBounds实现是最简便的,但是通过拦截器的实现方式是最优的方案。只需一次编写,所有的分页方法共同使用,还可以避免多次配置时的出错机率,需要修改时也只需要修改这一个文件,一劳永逸。而且是我们自己实现的,便于我们去控制和增加一些逻辑处理,使我们在外层更简单的使用。同时也不会出现数组分页和RowBounds分页导致的性能问题。当然,具体情况可以采取不同的解决方案。数据量小时,RowBounds不失为一种好办法。但是数据量大时,实现拦截器就很有必要了。
    
    到这里,mybatis的分页原理和全部实现过程都完成了,还有不清楚的可以自己去看一下mybatis的源码,按照这个思路去阅读还是比较清晰的。这里只是对插件(拦截器)实现分页做了个简单的介绍,只是简单的分页功能,还很简陋。在下一遍博客我们将会实现一个封装好的、功能齐全的实用性插件。传送门:mybatis精通之路之插件分页(拦截器)进阶 
    最后,希望大家提出宝贵意见,共同学习。
    1. 使用Map来进行包装数据实现分页功能
            1),在SQL语句映射的ResultType返回的是你要查询得到的实体类
            2),穿进去的参数parameterType是你自己包装的Map类型
            3),首先你传进来的参数要和SQL语句中的字段名要保持一致
            4),在实体DAO层还需要把查询数据的起始下标,和查询多少条数据都put进Map中
    
    SQL映射:
    
     <!--查询所有的用户信息,用map分页实现-->
        <select id="getAllMap" resultType="User" parameterType="Map">
            SELECT * FROM user limit #{startIndex},#{pageSize}
        </select>
    
    DAO实现类
    
    //这个是实现分页查询功能(用map来实现的第一种方式)
        public List<User> getAll(int currentPage,int pageSize) throws IOException {
            SqlSession  sqlSession = MybatisUtil.getSession();
            Map<String,Integer> map = new HashMap<String, Integer>();
    //这个是把当
            map.put("startIndex",(currentPage-1)*pageSize);
            map.put("pageSize",pageSize);
            List<User> list = sqlSession.selectList("UserMapper.getAllMap",map);
            sqlSession.close();
            return list;
        }
    
    测试类
    
    
        public static void main(String[] args) throws IOException {
            UserDao userDao = new UserDao();
            //这个传进来的第一个参数是你要显示第几页的数据,第二是你需要没页显示几条记录
            List<User> list = userDao.getAll(2, 3);
            for (User user : list) {
                System.out.println(user.toString());
            }
           }
    2. 使用RowBounds来实现分页
            1),只需要设置一个返回值为User实体类型
            2),RowBounds rowBounds= newRowBounds((currentPage-1)*pageSize,pageSize);
            3),就是上一步多了一个创建一个RowBounds对象,然后需要传入SQL语句中需要的参数就行了
            4),然后sqlSession在执行selectList的时候把那个rowBounds对象直接传进去就可以了
    
    SQL的xml映射
    
       <!--查询所有用户的信息,用RowBounds来实现-->
        <select id="getAllRowBounds" resultType="User">
            SELECT *FROM user
        </select>
    
    DAO实现类
    
     //这个是通过RowBounds来实现查询功能的分页操作
        public List<User> getAllRowBounds(int currentPage,int pageSize) throws IOException {
            SqlSession sqlSession = MybatisUtil.getSession();
            /*rowBounds需要的第一个参数就是从数据的哪个下标开始开始查,第二个就是你需要查询的条数*/
            RowBounds rowBounds= new RowBounds((currentPage-1)*pageSize,pageSize);
            List<User> list = sqlSession.selectList("UserMapper.getAllRowBounds",
                    null, rowBounds);
            sqlSession.close();
            return list;
        }
    
    测试类
    
    ublic class TestRowBounds {
    
        public static void main(String[] args) throws IOException {
            UserDao userDao = new UserDao();
            List<User> list = userDao.getAllRowBounds(1, 3);
            for (User user : list) {
                System.out.println(user.toString());
            }
        }
    }
  • 相关阅读:
    vps云服务器建站后绑定域名的方法?
    怎么做局域网远程联机?
    解决服务器Active&nbsp;Directory环境里Windows登录性能问题办法
    搭建dns域名服务器过程
    服务器电源常见故障判断及处理方法
    有些网站为什么要使用CDN,CDN又是什么呢
    独立服务器使用技巧介绍
    云服务器和虚拟主机的区别
    CDN在中国的发展的九个年头的点点滴滴
    网络安全的攻防战争
  • 原文地址:https://www.cnblogs.com/yaowen/p/9639035.html
Copyright © 2011-2022 走看看