Mybatis:(五)分页实现

一、相关知识回顾

  1. SqlSessionFactoryBuilder 的作用在于创建 SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 SqlSessionFactory 的方法中,而不要让其长期存在。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域
  2. SqlSessionFactory 可以被认为是一个数据库连接池,它的作用是创建 SqlSession 接口对象。因为 MyBatis 的本质就是 Java 对数据库的操作,所以 SqlSessionFactory 的生命周期存在于整个 MyBatis 的应用之中,所以一旦创建了 SqlSessionFactory,就要长期保存它,直至不再使用 MyBatis 应用,所以可以认为 SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。
  3. SqlSessionFactory 是一个对数据库的连接池,所以它占据着数据库的连接资源。如果创建多个 SqlSessionFactory,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。
  4. 在一般的应用中我们往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以说 SqlSessionFactory 的最佳作用域是应用作用域
  5. SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象
  6. SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象)以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try...catch...finally... 语句来保证其正确关闭。

二、日志工厂的实现

  1. 日志工厂罗列
  • SLF4J

  • Apache Commons Logging

  • Log4j 2

  • Log4j

  • JDK logging

    执行的日志工厂,会按顺序从所列举的日志工厂中找

  1. 日志实现

    <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
  2. log4j

    1. 简介:
    • Log4j是Apache的一个开源项目
    • 通过使用Log4j,我们可以控制日志信息输送的目的地:控制台,文本,GUI组件....
    • 我们也可以控制每一条日志的输出格式;
    • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
    1. 使用:
    • //导入log4j的包
      <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
      </dependency>
    • #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
      log4j.rootLogger=DEBUG,console,file
      
      #控制台输出的相关设置
      log4j.appender.console = org.apache.log4j.ConsoleAppender
      log4j.appender.console.Target = System.out
      log4j.appender.console.Threshold=DEBUG
      log4j.appender.console.layout = org.apache.log4j.PatternLayout
      log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
      
      #文件输出的相关设置
      log4j.appender.file = org.apache.log4j.RollingFileAppender
      log4j.appender.file.File=./log/ry.log
      log4j.appender.file.MaxFileSize=10mb
      log4j.appender.file.Threshold=DEBUG
      log4j.appender.file.layout=org.apache.log4j.PatternLayout
      log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
      
      #日志输出级别
      log4j.logger.org.mybatis=DEBUG
      log4j.logger.java.sql=DEBUG
      log4j.logger.java.sql.Statement=DEBUG
      log4j.logger.java.sql.ResultSet=DEBUG
      log4j.logger.java.sql.PreparedStatement=DEBUG
    • //setting设置日志实现
      <settings>
          <setting name="logImpl" value="LOG4J"/>
      </settings>
    • //注意导包:org.apache.log4j.Logger
      static Logger logger = Logger.getLogger(MyTest.class);
      
      @Test
      public void selectUser() {
          logger.info("info:进入selectUser方法");
          logger.debug("debug:进入selectUser方法");
          logger.error("error: 进入selectUser方法");
          SqlSession session = MybatisUtils.getSession();
          UserMapper mapper = session.getMapper(UserMapper.class);
          List<User> users = mapper.selectUser();
          for (User user: users){
              System.out.println(user);
          }
          session.close();
      }

三、分页

  1. 使用Limit实现分页

    #语法
    SELECT * FROM table LIMIT stratIndex,pageSize
    
    SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15   
    
    #为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:    
    SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.   
    
    #如果只给定一个参数,它表示返回最大的记录行数目:    
    SELECT * FROM table LIMIT 5; //检索前 5 个记录行

分页步骤

方式一:

  1. 修改Mapper文件

    <select id="selectUser" parameterType="map" resultType="user">
        select * from user limit #{startIndex},#{pageSize}
    </select>
  2. Mapper接口,参数为map

    //选择全部用户实现分页
    List<User> selectUser(Map<String,Integer> map);
  3. 起始位置 = (当前页面 - 1 ) * 页面大小

    //分页查询 , 两个参数startIndex , pageSize
    @Test
    public void testSelectUser() {
        SqlSession session = MybatisUtils.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
    
        int currentPage = 1;  //第几页
        int pageSize = 2;  //每页显示几个
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("startIndex",(currentPage-1)*pageSize);
        map.put("pageSize",pageSize);
    
        List<User> users = mapper.selectUser(map);
    
        for (User user: users){
            System.out.println(user);
        }
    
        session.close();
    }

方式二:RowBounds分页

  1. mapper接口

    //选择全部用户RowBounds实现分页
    List<User> getUserByRowBounds();
  2. mapper文件

    <select id="getUserByRowBounds" resultType="user">
      select * from user
    </select>
  3. 测试类:RowBounds类

    @Test
    public void testUserByRowBounds() {
        SqlSession session = MybatisUtils.getSession();
    
        int currentPage = 2;  //第几页
        int pageSize = 2;  //每页显示几个
        RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);
    
        //通过session.**方法进行传递rowBounds,[此种方式现在已经不推荐使用了]
        List<User> users = session.selectList("com.kuang.mapper.UserMapper.getUserByRowBounds", null, rowBounds);
    
        for (User user: users){
            System.out.println(user);
        }
        session.close();
    }

方式三:PageHelper插件

四、补充

  • selectList可以查询一条或多条记录。

  • selectOne: 查询一条记录

  • selectAll查询的是所有对象,selectOne查询的是一个对象并且需要设置条件,selectMap查询的是具有键值关系的对象

  • 说明:

    session.selectOne(“a.b.getUserById”, 1)里面的getUserById前面的名字要与SQL映射文件的mapper namespace=“a.b” 名字相对应,不然会无法加载文件