精华内容
下载资源
问答
  • mybatis分页查询

    千次下载 热门讨论 2015-12-28 00:04:59
    mybatis分页查询,spring + maven + mybatis实现分页查询源码
  • mybatis分页查询例子 idea实现, 分页查询,员工工资。
  • Mybatis分页查询

    万次阅读 多人点赞 2018-11-04 10:35:54
    分页查询作为数据库交互最常用的几种操作之一,在日常开发中是非常常见的,比如前段请求需要一个分页的列表,往往有两种方式,一是把所有的数据都给到前段,前段分页。另外一种方式是前端通过传分页信息给后端,后端...

    分页查询作为数据库交互最常用的几种操作之一,在日常开发中是非常常见的,比如前段请求需要一个分页的列表,往往有两种方式,一是把所有的数据都给到前段,前段分页。另外一种方式是前端通过传分页信息给后端,后端查询时进行分页,并将相应页的数据返给前端。第一种方式如果数据规模比较小的情况下可以使用,如果数据量较大,对内存、网络传输的消耗都是非常大的,所以实际开发中一般很少使用。第二种方式是后端进行分页,后端分页的实现又可以分为逻辑分页和物理分页,逻辑分页就是在进行数据库查询时一次性将数据查出来,然后将相应页的数据挑出返回,物理分页就是通过在查询时就查询相应的页的数据(比如直接在mysql查询语句添加limit)。很明显逻辑分页跟第一种前端分页的方式有着相同的弊端。

    之前写了好几篇关于Mybatis的文章了,其实mybatis原生也是支持分页的,但为了与数据库语法解耦,实现的是逻辑分页,首先将所有结果查询出来,然后通过计算offset和limit,只返回部分结果,操作在内存中进行,所以也叫内存分页,Mybatis逻辑分页是通过RowBounds实现的。而物理分页一般是通过为sql添加limit实现的,具体可以通过拦截器在对其后的第一个执行sql进行拦截,并自动拼接上分页的sql语句,也可以直接改造mapper.xml文件添加limit的方式实现。本文会分别介绍一下RowBounds逻辑分页、拦截器物理分页、改造mapper.xml这三种分页方式的使用方法。

    1. 逻辑分页——RowBounds

    通过RowBounds类可以实现Mybatis逻辑分页,原理是首先将所有结果查询出来,然后通过计算offset和limit,只返回部分结果,操作在内存中进行,所以也叫内存分页。弊端很明显,当数据量比较大的时候,肯定是不行的,所以一般不会去使用RowBounds进行分页查询,这里仅展示一下RowBounds用法。Mybatis Generator原生支持RowBounds查询,生成的Mapper接口中存在一个方法selectByExampleWithRowbounds就是通过RowBounds进行分页查询。

    1.1 项目结构

    |   pom.xml
    |   springboot-08-mybatis-rowbounds.iml
    |
    +---src
    |   +---main
    |   |   +---java
    |   |   |   \---com
    |   |   |       \---zhuoli
    |   |   |           \---service
    |   |   |               \---springboot
    |   |   |                   \---mybatis
    |   |   |                       \---rowbounds
    |   |   |                           |   SpringBootMybatisRowBoundsApplicationContext.java
    |   |   |                           |
    |   |   |                           +---controller
    |   |   |                           |       UserController.java
    |   |   |                           |
    |   |   |                           +---repository
    |   |   |                           |   +---conf
    |   |   |                           |   |       DataSourceConfig.java
    |   |   |                           |   |
    |   |   |                           |   +---mapper
    |   |   |                           |   |       UserMapper.java
    |   |   |                           |   |
    |   |   |                           |   +---model
    |   |   |                           |   |       User.java
    |   |   |                           |   |       UserExample.java
    |   |   |                           |   |
    |   |   |                           |   \---service
    |   |   |                           |       |   UserRepository.java
    |   |   |                           |       |
    |   |   |                           |       \---impl
    |   |   |                           |               UserRepositoryImpl.java
    |   |   |                           |
    |   |   |                           \---service
    |   |   |                               |   UserControllerService.java
    |   |   |                               |
    |   |   |                               \---impl
    |   |   |                                       UserControllerServiceImpl.java
    |   |   |
    |   |   \---resources
    |   |       |   application.properties
    |   |       |
    |   |       +---autogen
    |   |       |       generatorConfig_zhuoli.xml
    |   |       |
    |   |       \---base
    |   |           \---com
    |   |               \---zhuoli
    |   |                   \---service
    |   |                       \---springboot
    |   |                           \---mybatis
    |   |                               \---rowbounds
    |   |                                   \---repository
    |   |                                       \---mapper
    |   |                                               UserMapper.xml
    |   |
    |   \---test
    |       \---java

    1.2 pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.zhuoli.service</groupId>
        <artifactId>springboot-08-mybatis-rowbounds</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <!-- Spring Boot 启动父依赖 -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.3.RELEASE</version>
        </parent>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-maven-plugin</artifactId>
                    <version>1.3.5</version>
                    <!--如果不配置configuration节点,配置文件名字必须为generatorConfig.xml-->
                    <configuration>
                        <!--可以自定义generatorConfig文件名-->
                        <configurationFile>src/main/resources/autogen/generatorConfig_zhuoli.xml</configurationFile>
                        <verbose>true</verbose>
                        <overwrite>true</overwrite>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <dependencies>
            <!-- Exclude Spring Boot's Default Logging -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.2</version>
                <scope>provided</scope>
            </dependency>
    
        </dependencies>
    
    </project>

    1.3 数据源配置

    @Configuration
    @MapperScan(basePackages = "com.zhuoli.service.springboot.mybatis.rowbounds.repository.mapper", sqlSessionFactoryRef = "sqlSessionFactory")
    public class DataSourceConfig {
        @Value("${test.datasource.url}")
        private String url;
    
        @Value("${test.datasource.username}")
        private String user;
    
        @Value("${test.datasource.password}")
        private String password;
    
        @Value("${test.datasource.driverClassName}")
        private String driverClass;
    
        @Bean(name = "dataSource")
        public DataSource dataSource() {
            PooledDataSource dataSource = new PooledDataSource();
            dataSource.setDriver(driverClass);
            dataSource.setUrl(url);
            dataSource.setUsername(user);
            dataSource.setPassword(password);
            return dataSource;
        }
    
        @Bean(name = "transactionManager")
        public DataSourceTransactionManager dataSourceTransactionManager() {
            return new DataSourceTransactionManager(dataSource());
        }
    
        @Bean(name = "sqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
            final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
            sessionFactory.setDataSource(dataSource);
    
            /*设置mapper文件位置*/
            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                    .getResources("classpath:base/com/zhuoli/service/springboot/mybatis/rowbounds/repository/mapper/*.xml"));
    
            /*设置打印sql*/
            org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
            configuration.setLogImpl(StdOutImpl.class);
            sessionFactory.setConfiguration(configuration);
    
            return sessionFactory.getObject();
        }
    }

    为了展示RowBounds为逻辑分页,特地设置将sql控制台打印。

    1.4 Repository定义

    @Repository
    @AllArgsConstructor
    public class UserRepositoryImpl implements UserRepository {
    
        private UserMapper userMapper;
    
        @Override
        public List<User> getUserByRowBounds(String userName, String description, RowBounds rowBounds) {
            UserExample example = new UserExample();
            /*动态sql,userName和description不为null,则作为查询条件查询*/
            UserExample.Criteria criteria = example.createCriteria();
            if (!StringUtils.isNullOrEmpty(userName)) {
                criteria.andUserNameLike("%" + userName + "%");
            }
            if (!StringUtils.isNullOrEmpty(description)) {
                criteria.andDescriptionEqualTo(description);
            }
            return userMapper.selectByExampleWithRowbounds(example, rowBounds);
        }
    }

    1.5 Service层调用

    @Service
    @AllArgsConstructor
    public class UserControllerServiceImpl implements UserControllerService {
        private UserRepository userRepository;
    
        @Override
        public List<User> getByRowBounds(String userName, String description, Integer pageNum, Integer pageSize) {
            RowBounds rowBounds = new RowBounds((pageNum - 1) * pageSize, pageSize);
            return userRepository.getUserByRowBounds(userName, description, rowBounds);
        }
    }

    1.6 控制台信息

    Creating a new SqlSession
    SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cdf4b86] was not registered for synchronization because synchronization is not active
    JDBC Connection [com.mysql.jdbc.JDBC4Connection@373e86a1] will not be managed by Spring
    ==>  Preparing: select id, user_name, description, is_deleted from user WHERE ( user_name like ? ) 
    ==> Parameters: %zhuoli%(String)
    <==    Columns: id, user_name, description, is_deleted
    <==        Row: 6, zhuoli, zhuoli is a programer, 0
    <==        Row: 7, zhuoli1, zhuoli1 is a programer, 0
    Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cdf4b86]

    sql查询时并没有添加limit,也验证了之前讲的RowBounds分页原理是首先将所有结果查询出来,然后通过计算offset和limit,只返回部分结果,是一种逻辑分页。至于Mybatis RowBounds分页原理,请查看Mybatis逻辑分页原理解析RowBounds,写的挺明白的。

    2. 物理分页——直接为sql添加limit

    如果可以在查询时直接在sql中指定limit,name肯定是只查询相应页的数据。所以就有一种直观的现象,比如使用mybatis,如果可以在mapper.xml中添加limit属性,那生成的sql肯定是可以直接查询到相应页的数据的。结合之前使用的Mybatis Generator,可以这样实现:首先在生成的XxxExample中加入两个属性limit和offset,同时加上set和get方法,然后在XxxMapper.xml中在通过selectByExample查询时,添加limit,大概就是这种样子:

    /*XxxExample*/
    private Integer limit;
    private Integer offset;
    public void setLimit(Integer limit) {
        this.limit = limit;
    }
    public Integer getLimit() {
        return limit;
    }
    public void setOffset(Integer offset) {
        this.offset = offset;
    }
    public Integer getOffset() {
        return offset;
    }
    
    /*XxxMapper.xml*/
    <select id="selectByExample" parameterType="com.xxg.bean.XxxExample" resultMap="BaseResultMap">
      ...
      <if test="limit != null">
        <if test="offset != null">
          limit ${offset}, ${limit}
        </if>
        <if test="offset == null">
          limit ${limit}
        </if>
      </if>
    </select>

    其实手动去加工作量也不大,但是如果表比较多,添加起来还是有一定工作量的。而且加入下次表结构变更,重新通过Mybatis Generator生成的话,这些信息也要重新加入。为了避免这些麻烦,有大神写了一个Mybatis Generator插件MySQLLimitPlugin,可以在Mybatis Generator生成文件的时候自动生成上述信息,本片文章就使用MySQLLimitPlugin插件进行生成。

    2.1 pom.xml

    项目结构跟RowBounds一致,这里不单独放出来了,首先来看一下pom.xml配置。为了使用MySQLLimitPlugin插件,这里要声明MySQLLimitPlugin仓库地址,并为Mybaits Generator添加MySQLLimitPlugin依赖。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.zhuoli.service</groupId>
        <artifactId>springboot-08-mybatis-limitplugin</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <!-- Spring Boot 启动父依赖 -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.3.RELEASE</version>
        </parent>
    
        <!--声明MysqlLimitPlugin maven仓库地址-->
        <pluginRepositories>
            <pluginRepository>
                <id>mybatis-generator-limit-plugin-mvn-repo</id>
                <url>https://raw.github.com/wucao/mybatis-generator-limit-plugin/mvn-repo/</url>
            </pluginRepository>
        </pluginRepositories>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-maven-plugin</artifactId>
                    <version>1.3.5</version>
                    <!--如果不配置configuration节点,配置文件名字必须为generatorConfig.xml-->
                    <configuration>
                        <!--可以自定义generatorConfig文件名-->
                        <configurationFile>src/main/resources/autogen/generatorConfig_zhuoli.xml</configurationFile>
                        <verbose>true</verbose>
                        <overwrite>true</overwrite>
                    </configuration>
    
                    <!--为MybatisGenerator添加MySQLLimitPlugin,为生成的Example类添加limit和offset属性,为生成的mapper.xml文件selctByExample添加Limit-->
                    <dependencies>
                        <dependency>
                            <groupId>com.xxg</groupId>
                            <artifactId>mybatis-generator-plugin</artifactId>
                            <version>1.0.0</version>
                        </dependency>
                    </dependencies>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <dependencies>
            <!-- Exclude Spring Boot's Default Logging -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.2</version>
                <scope>provided</scope>
            </dependency>
    
        </dependencies>
    

    2.2 Mybatis Generator配置文件添加MySQLLimitPlugin依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    <generatorConfiguration>
    
        <!--注意:本地需要有mysql-connector-java-5.1.45-bin.jar-->
        <classPathEntry location="D:\\mysql-connector-java-5.1.45-bin.jar"/>
        <context id="DB2Tables" targetRuntime="MyBatis3">
    
            <!-- 省略 -->
    
            <plugin type="org.mybatis.generator.plugins.RowBoundsPlugin"/>
            <plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
            <!--添加MySQLLimitPlugin,为生成的Example类添加limit和offset属性,为生成的mapper.xml文件selctByExample添加Limit-->
            <plugin type="com.xxg.mybatis.plugins.MySQLLimitPlugin"/>
    
            <!-- 省略 -->
    
        </context>
    </generatorConfiguration>

    2.3 Repository定义

    数据源定义跟RowBounds数据源定义一致,这里不单独放出来了,直接看一下limit在respository的使用:

    @Repository
    @AllArgsConstructor
    public class UserRepositoryImpl implements UserRepository {
    
        private UserMapper userMapper;
    
        @Override
        public List<User> getUserByExampleLimit(String userName, String description, Integer pageNum, Integer pageSize) {
            UserExample example = new UserExample();
            /*动态sql,userName和description不为null,则作为查询条件查询*/
            UserExample.Criteria criteria = example.createCriteria();
            if (!StringUtils.isNullOrEmpty(userName)) {
                criteria.andUserNameLike("%" + userName + "%");
            }
            if (!StringUtils.isNullOrEmpty(description)) {
                criteria.andDescriptionEqualTo(description);
            }
            example.setOffset((pageNum - 1) * pageSize);
            example.setLimit(pageSize);
            return userMapper.selectByExample(example);
        }
    }

    2.4 Service层调用

    @Service
    @AllArgsConstructor
    public class UserControllerServiceImpl implements UserControllerService {
        private UserRepository userRepository;
    
        @Override
        public List<User> getUserByExampleLimit(String userName, String description, Integer pageNum, Integer pageSize) {
            return userRepository.getUserByExampleLimit(userName, description, pageNum, pageSize);
        }
    }

    2.5 控制台信息

    Creating a new SqlSession
    SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@706f956b] was not registered for synchronization because synchronization is not active
    JDBC Connection [com.mysql.jdbc.JDBC4Connection@7234b5ae] will not be managed by Spring
    ==>  Preparing: select id, user_name, description, is_deleted from user WHERE ( user_name like ? ) limit 0, 10 
    ==> Parameters: %zhuoli%(String)
    <==    Columns: id, user_name, description, is_deleted
    <==        Row: 6, zhuoli, zhuoli is a programer, 0
    <==        Row: 7, zhuoli1, zhuoli1 is a programer, 0
    <==        Row: 8, zhuoli2, zhuoli2 is a programer, 0
    <==      Total: 3
    Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@706f956b]

    可以看到sql查询时,limit参数是固定的,也就是说通过Example成功将limit参数添加到生成的sql中,这种方式的分页是一种物理分页,有些情况也是必须要这么做的。比如我之前做过一个使用Zebra进行分库分表的项目,在使用拦截器进行分页时,并不起作用,原因不明,到最后只好通过这种方式实现分库分表的分页查询。至于原因,一直没来及查清楚,回头有时间的话,我会用一篇文章讲述。

    3. 物理分页——拦截器PageHelper

    PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件,在配置了PageHelper的page number和size,调用完startPage后,它会通过PageInterceptor对其后的第一个执行sql进行拦截,比如List<User> list = userService.findAllUser(),这里原本的sql可能是 select * from users,它会自动拼接上分页的sql语句,比如mysql环境的话,就是拼接上limit语句,随后执行,最后的结果,可以通过PageInfo和Page进行获取。

    3.1 pom.xml

    项目结构跟RowBounds一致,这里不单独放出来了,首先来看一下pom.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.zhuoli.service</groupId>
        <artifactId>springboot-08-mybatis-pagehelper</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <!-- Spring Boot 启动父依赖 -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.3.RELEASE</version>
        </parent>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-maven-plugin</artifactId>
                    <version>1.3.5</version>
                    <!--如果不配置configuration节点,配置文件名字必须为generatorConfig.xml-->
                    <configuration>
                        <!--可以自定义generatorConfig文件名-->
                        <configurationFile>src/main/resources/autogen/generatorConfig_zhuoli.xml</configurationFile>
                        <verbose>true</verbose>
                        <overwrite>true</overwrite>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <dependencies>
            <!-- Exclude Spring Boot's Default Logging -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <!--pagehelper -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>1.2.5</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.2</version>
                <scope>provided</scope>
            </dependency>
    
        </dependencies>
    
    </project>

    3.2 Repository定义

    @Repository
    @AllArgsConstructor
    public class UserRepositoryImpl implements UserRepository {
    
        private UserMapper userMapper;
    
        @Override
        public List<User> getUserByCondition(String userName, String description) {
            UserExample example = new UserExample();
            /*动态sql,userName和description不为null,则作为查询条件查询*/
            UserExample.Criteria criteria = example.createCriteria();
            if (!StringUtils.isNullOrEmpty(userName)) {
                criteria.andUserNameLike("%" + userName + "%");
            }
            if (!StringUtils.isNullOrEmpty(description)) {
                criteria.andDescriptionEqualTo(description);
            }
            return userMapper.selectByExample(example);
        }
    }

    可以看到,respository层没有任何分页相关的信息,使用Rowbounds要传入一个RowBounds参数,使用MySQLLimitPlugin要把pageNum和pageSize作为参数传入。所以可以很明显看到一个好处是,使用PageHelper是非侵入的,假如respository层有N个查询方法,在做分页时,不用改造respository层代码,使方法的通用性更高。

    3.3 service层调用

    @Service
    @AllArgsConstructor
    public class UserControllerServiceImpl implements UserControllerService {
        private UserRepository userRepository;
    
        @Override
        public PageInfo<User> getByCondition(String userName, String description, Integer pageNum, Integer pageSize) {
            //分页
            PageHelper.startPage(pageNum, pageSize);
            List<User> queryResult = userRepository.getUserByCondition(userName, description);
            return new PageInfo<>(queryResult);
        }
    }

    3.4 控制台信息

    SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2057e3b5] was not registered for synchronization because synchronization is not active
    Cache Hit Ratio [SQL_CACHE]: 0.0
    JDBC Connection [com.mysql.jdbc.JDBC4Connection@487a7b05] will not be managed by Spring
    ==>  Preparing: SELECT count(0) FROM user WHERE (user_name LIKE ?) 
    ==> Parameters: %zhuoli%(String)
    <==    Columns: count(0)
    <==        Row: 3
    <==      Total: 1
    ==>  Preparing: select id, user_name, description, is_deleted from user WHERE ( user_name like ? ) LIMIT ?, ? 
    ==> Parameters: %zhuoli%(String), 2(Integer), 2(Integer)
    <==    Columns: id, user_name, description, is_deleted
    <==        Row: 8, zhuoli2, zhuoli2 is a programer, 0
    <==      Total: 1
    Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2057e3b5]

    3.5 PageInfo输出

    {
      "total": 3,
      "list": [
        {
          "id": 8,
          "userName": "zhuoli2",
          "description": "zhuoli2 is a programer",
          "isDeleted": 0
        }
      ],
      "pageNum": 2,
      "pageSize": 2,
      "size": 1,
      "startRow": 3,
      "endRow": 3,
      "pages": 2,
      "prePage": 1,
      "nextPage": 0,
      "isFirstPage": false,
      "isLastPage": true,
      "hasPreviousPage": true,
      "hasNextPage": false,
      "navigatePages": 8,
      "navigatepageNums": [
        1,
        2
      ],
      "navigateFirstPage": 1,
      "navigateLastPage": 2,
      "firstPage": 1,
      "lastPage": 2
    }

    可以到,分页相关的基本信息都拿到了,可以说是非常方便的。

    示例代码:

    码云 – 卓立 – Mybatis使用RowBounds分页

    码云 – 卓立 – Mybatis使用MySQLLimitPlugin分页

    码云 – 卓立 – Mybatis使用PageHelper分页

    参考链接:

    1. Mybatis逻辑分页原理解析RowBounds
    2. Mybatis最入门—分页查询(逻辑分页与SQL语句分页)
    3. MyBatis Generator实现MySQL分页插件
    4. Mybatis3.4.x技术内幕(二十):PageHelper分页插件源码及原理剖析
    展开全文
  • Mybatis分页查询(通过SQL分页实现) 前言 实现有哪几种方式: 网页分页 (一次查询所有数据,加载到网页,那么适合数量小的操作) 服务器端分页 java程序中查询所有数据,网页需要哪一页,就给哪一页数据,会撑...

    Mybatis分页查询(通过SQL分页实现)

    前言

    实现有哪几种方式:

    1. 网页分页

      (一次查询所有数据,加载到网页,那么适合数量小的操作)

    2. 服务器端分页

      java程序中查询所有数据,网页需要哪一页,就给哪一页数据,会撑爆java服务器,建议查询缓存优化

    3. 数据库分页

      请求一页数据,查询数据库即可

    本文采用Oracle中的rownum实现分页,数据表使用Oracle中Scott的EMP表

    一、搭建环境

    目录结构

    在这里插入图片描述

    1. 导入jar包

      mybatis-3.2.7.jar
      ojdbc6.jar

    2. 数据库配置文件(db.properties)

      db.driver=oracle.jdbc.driver.OracleDriver
      db.url=jdbc:oracle:thin:@10.25.164.149:1521:orcl
      db.username=scott
      db.password=123456
      
    3. mybatis-config.xml

      <environments default="development">
          <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
              <property name="driver" value="${db.driver}"/>
              <property name="url" value="${db.url}"/>
              <property name="username" value="${db.username}"/>
              <property name="password" value="${db.password}"/>
            </dataSource>
          </environment>
          
      
        </environments>
        <mappers>
        <!-- 这是映射文件,一个表一个,我们的sql就写在这里 -->
          <mapper resource="config/EmpMapper.xml"/>
        </mappers>
      </configuration>
      
      
    4. MybatisUtils.java

      package net.neuedu.mybatis3.util;
      
      import java.io.IOException;
      import java.io.InputStream;
      
      import org.apache.ibatis.io.Resources;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.apache.ibatis.session.SqlSessionFactoryBuilder;
      
      public class MybatisUtils {
      	
      	private static SqlSessionFactory sqlSessionFactory;
      	
      	static
      	{
      		String resource = "config/mybatis-config.xml";
      		
      		InputStream inputStream=null;
      		try {
      			inputStream = Resources.getResourceAsStream(resource);
      		} catch (IOException e) {
      			e.printStackTrace();
      		}finally
      		{
      		}
      		sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
      		
      	}
      	
      	public static SqlSession getSqlSession()
      	{
      		SqlSession sqlSession=null;
      		
      		sqlSession=sqlSessionFactory.openSession();
      		
      		return sqlSession;
      	}
      
      }
      

    二、创建实体类

    Emp.java

    package net.neuedu.mybatis3.domain;
    
    import java.math.BigDecimal;
    import java.util.Date;
    
    public class Emp {
    	 private Integer empno;private String ename;private String job;private Short mgr;private Date hiredate;private BigDecimal sal;private BigDecimal comm;
    
      //  private Short deptno;
    
    
    ​	   
    
    ​    public Integer getEmpno() {return empno;}@Overridepublic String toString() {return "Emp [empno=" + empno + ", ename=" + ename + ", job=" + job
    
       + ", mgr=" + mgr + ", hiredate=" + hiredate + ", sal="
    
            + sal + ", comm=" + comm + "]";
              }
    
         public void setEmpno(Integer empno) {
         	this.empno = empno;
         }
    
         public String getEname() {
         return ename;
             }public void setEname(String ename) {this.ename = ename == null ? null : ename.trim();}public String getJob() {return job;}public void setJob(String job) {this.job = job == null ? null : job.trim();}public Short getMgr() {return mgr;}public void setMgr(Short mgr) {this.mgr = mgr;}public Date getHiredate() {return hiredate;}public void setHiredate(Date hiredate) {this.hiredate = hiredate;}public BigDecimal getSal() {return sal;}public void setSal(BigDecimal sal) {this.sal = sal;}public BigDecimal getComm() {return comm;}public void setComm(BigDecimal comm) {this.comm = comm;}
    
    //	    public Short getDeptno() {
    //	        return deptno;
    //	    }
    //
    //	    public void setDeptno(Short deptno) {
    //	        this.deptno = deptno;
    //	    }
    }
    

    三、EmpMapper接口

    public interface EmpMapper {
    /**
     * 查询员工表中一共有多少条数据
     * @return
     */
    public Integer selectSize();
    
    /**
     * 分页查询
     * @param pageUtil
     * @return
     */
    public List<Emp> selectEmpByPage(PageUtil pageUtil);}
    

    四、分页工具类

    PageUtil.java

    package net.neuedu.mybatis3.domain;
    
    
    
    /**
     * 具体功能:告诉他每页显示几条数据,和一共有多少数据,还有显示第几页数据,它帮我们算出需要分多少页,每页的起始索引
     * @author hp
     *
     */
    public class PageUtil {
    	
    	public final static int PAGECOUNT=3;//每页显示几条数据   3
    	private int pageNumber;//显示第几页数据  1
    	private int size;// 一共有多少条数据   3
    	private int startIndex;//对应页面开始的索引 include
    	private int endIndex;//对应页面结束的索引      不包含
    	private int pageNums;//一共有多少页
    	
    	
    	@Override
    	public String toString() {
    		return "PageUtil [pageCount=" + PAGECOUNT + ", pageNumber="
    				+ pageNumber + ", size=" + size + ", startIndex=" + startIndex
    				+ ", endIndex=" + endIndex + ", pageNums=" + pageNums + "]";
    	}
    
    	/**
    	 * 构造方法:需要三个参数,每页显示几条数据,一共有多少条数据,显示第几页数据
    	 * @param pageCount
    	 * @param size
    	 * @param pageNumber
    	 */
    	public PageUtil(int pageCount,int size,int pageNumber)
    	{
    		//根据参数给对应属性赋值
    		this.pageNumber=pageNumber;
    		this.size=size;
    		
    		//帮我们算出需要分多少页,每页的起始索引
    		this.pageNums=size%pageCount==0?size/pageCount:size/pageCount+1;
    		this.startIndex=this.PAGECOUNT*(pageNumber-1)+1;//0
    		
    		if(pageNumber==pageNums)//如果请求页码刚好是最后一页,那么结束索引要好好计算一下
    		{
    			this.endIndex=size;
    		}else {
    			this.endIndex=this.PAGECOUNT*pageNumber; 
    		}
    		
    		//处理pageNumber=0的情况
    		if(pageNumber==0)
    		{
    			this.startIndex=0;
    			this.endIndex=0;
    		}
    	}
    	
    	public static void main(String[] args) {
    		PageUtil pageUtil=new PageUtil(10, 3,1);//13页, 10-20
    		System.out.println(pageUtil);
    	}
    	
    	
    	public int getPageNumber() {
    		return pageNumber;
    	}
    	public void setPageNumber(int pageNumber) {
    		this.pageNumber = pageNumber;
    	}
    	public int getSize() {
    		return size;
    	}
    	public void setSize(int size) {
    		this.size = size;
    	}
    	public int getStartIndex() {
    		return startIndex;
    	}
    	public void setStartIndex(int startIndex) {
    		this.startIndex = startIndex;
    	}
    	public int getEndIndex() {
    		return endIndex;
    	}
    	public void setEndIndex(int endIndex) {
    		this.endIndex = endIndex;
    	}
    	public int getPageNums() {
    		return pageNums;
    	}
    	public void setPageNums(int pageNums) {
    		this.pageNums = pageNums;
    	}
    }
    
    

    五、SQL实现分页

    EmpMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="net.neuedu.mybatis3.mapper.EmpMapper">
        <!--查询员工表中一共有多少条数据 public Integer selectSize(); -->
        <select id="selectSize" resultType="Integer">select count(1) from emp</select>
        <!-- /**    * 分页查询    * @param pageUtil    * @return    */   -->      
        <select id="selectEmpByPage" parameterType="PageUtil" resultType="Emp"> 
            select ee.*      from      
            (select e.*,rownum rn from emp e       
            where rownum<![CDATA[<=]]>#{endIndex}) ee      
            where ee.rn>=#{startIndex}   
        </select>  
    </mapper>
    

    测试

    package test;
    
    import java.util.List;
    
    import net.neuedu.mybatis3.domain.Emp;
    import net.neuedu.mybatis3.domain.PageUtil;
    import net.neuedu.mybatis3.mapper.EmpMapper;
    import net.neuedu.mybatis3.util.MybatisUtils;
    
    import org.apache.ibatis.session.SqlSession;
    
    public class TestPageSQL {
    
    	public static void main(String[] args) {
    		
    		SqlSession sqlSession=MybatisUtils.getSqlSession();
    		
    		EmpMapper mapper=sqlSession.getMapper(net.neuedu.mybatis3.mapper.EmpMapper.class);
    		//查询员工表中一共有多少条数据
    		Integer size=mapper.selectSize();
    		//实例化分页工具类,它会帮我们算出开始索引和结束索引
    		PageUtil pageUtil=new PageUtil(3, size, 5);
    		//分页查询
    		List<Emp> list=mapper.selectEmpByPage(pageUtil);
    		
    		System.out.println(list.toString());
    		
    		sqlSession.close();
    
    	}
    
    }
    
    

    测试结果

    在这里插入图片描述
    [

    展开全文
  • 本例子使用 SpringMVC + Mybatis 框架整合, 基于 Spring 注解实现, 省去了 Spring 繁琐的 bean 手工配置,实现的功能包括: 1、 用户登录、注销 2、 登录界面生成验证码图片 3、 用户表数据的增、删、改、查、分页...
  • Mysql+Mybatis分页查询

    千次阅读 2018-12-16 19:40:25
    一,首先做一个查询所有并显示 dao public interface ProductDAO { public List&lt;Product&gt; list(); } mapper &lt;mapper namespace="hust.mm.dao.ProductDAO"&gt; &lt;...

    一,首先做一个查询所有并显示

    dao

    public interface ProductDAO {
    	public List<Product> list();
    }

    mapper

    <mapper namespace="hust.mm.dao.ProductDAO">
    	<select id="list" resultType="Product">
    		select * from product
    	</select>
    </mapper>

    controller

    @RequestMapping("/list.do")
    public ModelAndView productlist(){
    	ModelAndView mav = new ModelAndView();
    		
    	List<Product> products = productDao.list();
    		
    	mav.addObject("products", products);
    	mav.setViewName("productList");
    		
    	return mav;
    }

    jsp

    <table align="center">
    		<th>
    			<td>id</td>
    			<td>name</td>
    			<td>price</td>
    		</th>
    		<c:forEach items="${products }" var="p" varStatus="st">
    			<tr>
    				<td>${p.id }</td>
    				<td>${p.name }</td>
    				<td>${p.price }</td>
    			</tr>
    		</c:forEach>
    </table>

    以上简要给出了一个表中的所有数据

    二,分页显示

    修改dao

    public interface ProductDAO {
    	public List<Product> list();
    	public List<Product> list(@Param("start") int start, @Param("count") int count);
    }

    修改mapper

    <mapper namespace="hust.mm.dao.ProductDAO">
        <select id="list" resultType="Product">
    		select * from product
    		<if test="start!=null and count!=null">
    			limit #{start},#{count}
    		</if>
    	</select>
    </mapper>

    修改controller

    @RequestMapping("/list.do")
    public ModelAndView productlist(int start){
    	ModelAndView mav = new ModelAndView();
    		
    	List<Product> products = productDao.list(start,3);
    		
    	mav.addObject("products", products);
    	mav.addObject("start", start);
    	mav.setViewName("productList");
    		
    	return mav;
    }

    修改jsp

    <table align="center">
    		<th>
    			<td>id</td>
    			<td>name</td>
    			<td>price</td>
    		</th>
    		<c:forEach items="${products }" var="p" varStatus="st">
    			<tr>
    				<td>${p.id }</td>
    				<td>${p.name }</td>
    				<td>${p.price }</td>
    			</tr>
    		</c:forEach>
            
            <tr>
    			<td><a href="list.do?start=${start-3 }">上一页</a></td>
    			<td><a href="list.do?start=${start+3 }">下一页</a></td>
    		</tr>
    </table>

    这里以每页三条数据分页显示

    三,完善分页

    可以想到,当在首页点击上一页和在尾页点击下一页,应该没有反应或者做出相应处理。有两种解决方案,

    1. 使用jstl或el语句判断start参数是否小于0或大于total-分页大小
    2. 在controller对start进行判断

    四,分页的其他方案

    上述的分页是利用了mybatis的动态SQL以及MySQL数据库特有的limit语句。有一定的特殊性,可以使用PageHelper这一类分页插件来进行分页开发。

     

    展开全文
  • idea+spring boot+mybatis分页查询

    千次阅读 2019-07-18 18:05:49
    这里的分页使用的是mybatis的分页插件PagehHelper,话不多说,开始我们的分页之旅。...--mybatis分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> ...

    这里的分页使用的是mybatis的分页插件PagehHelper,话不多说,开始我们的分页之旅。
    第一步:在pom.xml添加mybatis插件依赖

     <!--mybatis分页插件-->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>1.2.5</version>
            </dependency>
    

    第二步:在配置文件中加入以下配置

    #分页插件的配置
    pagehelper.helper-dialect=mysql
    pagehelper.reasonable=true
    pagehelper.supportMethodsArguments=true
    pagehelper.params=count=countSq
    

    第三步:编写分页代码(这里我只写部分逻辑代码,只要掌握写法就ok了)

    @RestController
    @RequestMapping("/role")
    public class RoleController {
        @Autowired(required = false)
        RoleServiceImpl roleService;
        @RequestMapping("/list")
        public Object findRoleAll(int pageNum,int pageSize){
            ModelMap map =new ModelMap();
            //pageNum:当前第几页   pageSize:每页的数量
            PageHelper.startPage(pageNum,pageSize);
            try {
                List<Role> roleAll = roleService.findRoleAll();
                //分页的信息
                PageInfo<Role>pageInfo=new PageInfo<>(roleAll);
                map.put("msg","查询所有角色成功");
                map.put("data",pageInfo);
                map.put("code",0);
            }catch (Exception e){
                e.getStackTrace();
                map.put("msg","查询所有角色失败");
                map.put("code",1);
            }
            return map;
        }
    
    

    第四步:使用postmain测试工具进行测试,得到如下图结果:
    传参:
    在这里插入图片描述
    返回的数据:total:数据总量 list:查询得到的数据
    在这里插入图片描述
    这里只是Java其中一种分页的方式,上手容易,操作简单

    展开全文
  • mybatis分页查询与筛选

    千次阅读 2020-05-15 09:31:58
    mybatis查询(可分页或不分页) <select id="getPicAndVideoList" resultMap="CarTypeDtoMap"> select ct.id, ct.carSystemId , rcs.name as car_system_name , ct.product_id, ct.product_code, ct.product_...
  • 在一次调试中,发现了一个bug,就是有三个大数据量的表进行关联查询分页,一个表60万,一个表40万,一个表20万,发现前端50页查询速度很快,但是当查询到5000页的时候,特别慢,需要两分钟。 素材: 语言:java ...
  • 解决Mybatis 分页插件pagehelper不支持逆向工程Example条件查询.含源码和jar包
  • cjs-mybatis-示例
  • TK-MyBatis 分页查询

    万次阅读 2018-08-10 14:30:02
    记 tkMybatis 查询出一个 List集合 该集合已经做好了一层分页Page封装 即查询出的list 使用类型判断 instanceof Page 为true 但是,中途不明白这是一个带分页的集合,把查询出的结果集又做了一层封装 需要返回的对象...
  • springboot项目进行整合了mybtis配置dbcp数据源,拦截器配置,静态资源访问,集成的分页查询和相关的事务配置,以及前端跳转的模板选择等,
  • 分页查询一般分成两次查询一次查总数一次查列表,下面这种写法可以一次返回 sql <resultMap id="queryOrderListResultMap" type="要返回数据的类型"> </resultMap> <resultMap type="Long" ...
  • oracle+mybatis分页查询

    千次阅读 2017-09-14 08:42:09
    当使用oracle进行分页查询时使用以下方式: SELECT *  FROM (SELECT A.*, ROWNUM RN  FROM (select t.name as name,  t.formula as formula,  t.data_from as dataFro
  • 一般物理分页,即通过sql语句分页,都是在sql语句后面添加limit分页语句,在xml文件里传入分页的参数,再多配置一条sql,用于查询总数: <select id="queryStudentsBySql" parameterType="map" resultMap=...
  • 笔者在修改那些渣渣写的代码时,遇到个bug:mybatis分页查询数据,总数大于10条,查询出来不足10条,看分页插件用的没有问题 原因:列表数据的resultMap里关联了附件的resultMap,可存在数据id重复问题,导致部分...
  • 正常使用postman工具调用测试接口,提供确定有数据的查询条件,分页参数是一页10条,显示第一条,返回数据中total是正常的,但是data中居然是一堆null的list,我第一反应是自己是不是写错了映射的实体类。...
  • Mybatis分页查询及日期比较

    千次阅读 2019-09-29 17:00:19
    怎么进行数据库分页查询,避免结果过于庞大,运行速度慢 怎么进行日期比较,从不同精度比较两个日期的大小 2. 样例数据库设计   假设存在这样一张user用户表,他的定义(MySql)如下: id name birthday ...
  • 步骤一:导入相关jar包 步骤二:在src下配置mybatis.xml配置...步骤四:配置映射文件,其中配置好相对应的sql分页查询的语句(这里以mysql为例) 步骤五:dao层中编写分页方法 mysql
  • SpringBoot + mybatis 分页查询

    万次阅读 2018-01-17 11:33:25
    使用的时候,只要简单配置,就可以在查询语句之后得到所需的分页信息。 1:在 pom.xml 中引入依赖项。 dependency> groupId>com.github.pagehelpergroupId> artifactId>pagehelperarti
  • 这个是用springmvc+mybatis来实现的分页查询,我觉得最值得借鉴的是如何搭建这个环境springmvc+mybatis,希望对大家有用。
  • Author:赵志乾 Date:2019-07-24 ...场景:分页查询带嵌套结果集合的Vo,如下: // 结果记录 package com.zhaozhiqian; import java.util.List; public class NodeVo { private String id; ...
  • 很明显的分页查询记录变少 机智的我立马想到了分页插件搞的鬼,然后百度了一下,果然,参考这篇 找到一点眉目了。 查询出来数据有重复的id导致pageHelper过滤掉了重复的数据 由于券规则码是一样的。所以只返回了一条...
  • Mybatis 分页查询数据(借用map来封装参数)  1、IEmpDAO.java 提供分页查询的方法 /** * 分页查询员工 * * @param cp * 当前页 * @param ps * 查询几条 * @return */ public List findEmpSplit...
  • 本人博客中的代码Jsp+Servlet+MyBatis完成分页查询 http://blog.csdn.net/japanstudylang/article/details/51700874
  • <mapper resource="com/xf/mybatis/mapper/UserMapperPage.xml"/> User: package com.xf.mybatis.pojo; public class User { private int id; private String username; private String password;...
  • 情景: 1.在使用MyBatis执行SQL(包含分页...解决方案:分页查询数据之前先清理分页缓存。 先执行 PageHelper.clearPage(); SQL代码如下:发现SQL中并没有LIMIT。 查询结果仅一页,期望的结果是多页。 查..
  • mybatis实现分页查询

    2020-08-01 22:01:12
    一,分页的sql语句 select * from account limitstartIndex,...二,mybatis实现分页查询 2.1数据库字段 2.2实体类 package cn.mybatis.pojo; public class Account { private int id; private Strin.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 71,315
精华内容 28,526
关键字:

mybatis分页查询