当前位置: 首页 > news >正文

【Mybatis】MyBatis分页的三种实现方式,Log4j的使用

文章目录

    • 分页的实现
      • 使用日志工厂看Log信息
        • Log4j
      • 方式一:SQL的`limit`关键字
        • SQL中`Limit`关键字的用法
        • 实现步骤:
      • 方式二:RowBounds分页(不推荐使用)
      • 方式三:PageHelper
        • 引入依赖
        • 配置plugins
        • 使用 PageHelper 进行分页查询
        • 页面显示如下
        • 优化分页内容显示

分页的实现

使用日志工厂看Log信息

思考:我们在测试SQL的时候,要是能够在控制台输出 SQL 的话,是不是就能够有更快的排错效率?

如果一个 数据库相关的操作出现了问题,我们可以根据输出的SQL语句快速排查问题。

对于以往的开发过程,我们会经常使用到debug模式来调节,跟踪我们的代码执行过程。但是现在使用Mybatis是基于接口配置文件的源代码执行过程。

我们必须选择日志工具来作为我们开发,调节程序的工具。

Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j
  • JDK logging

具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会使用最先找到的(按上文列举的顺序查找)。 如果一个都未找到,日志功能就会被禁用。

标准日志实现

指定 MyBatis 应该使用哪个日志记录实现。如果此设置不存在,则会自动发现日志记录实现。

<settings><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

测试,可以看到控制台有大量的输出!我们可以通过这些输出来判断程序到底哪里出了Bug

Log4j

简介:

  • Log4j是Apache的一个开源项目
  • 通过使用Log4j,我们可以控制日志信息输送的目的地:控制台文本,GUI组件….
  • 我们也可以控制每一条日志的输出格式;
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

使用步骤:

  1. 导入log4j的包
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
  1. 配置文件编写

没有编写 log4j的配置文件,Mybatis的log依旧打印出来了,,配置文件是在程序执行时需要用到的;

#将等级为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/kuang.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
  1. setting设置日志实现
<settings><setting name="logImpl" value="LOG4J"/>
</settings>
  1. 在程序中使用Log4j进行输出!

如果需要控制台打印的话 需要new一个Logger 对象,这样才能输出出来

//注意导包: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. 测试,看控制台输出!
  • 使用Log4j 输出日志
  • 可以看到还生成了一个日志的文件 【需要修改file的日志级别】

方式一:SQL的limit关键字

思考:为什么需要分页?

在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内

SQL中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 个记录行   #换句话说,LIMIT n 等价于 LIMIT 0,n。
实现步骤:
  1. 修改Mapper文件,注意parameterType的数据类型,根据需要设置;
<select id="selectUser" parameterType="map" resultType="user">select * from user limit #{startIndex},#{pageSize}
</select>
  1. 前面Mybatis中使用的map,这边就用Mapper接口,参数为map
//选择全部用户实现分页
List<User> selectUser(Map<String,Integer> map);
  1. 在测试类中传入参数测试

思路:startIndex =(currentPage-1)*pageSize

  • startIndex:起始位置
  • currentPage:当前页面
  • pageSize:页面件数
  1. 转化为web使用时,需要传入的值是,当前页数每页的页面件数
  2. map传入的起始位置是limit关键字 需要查询返回的第start~end条数据的起始数;
//分页查询 , 两个参数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();
}

画面显示不只有做这些:

  1. 转化为web使用时,需要传入的值是,当前页数每页的页面件数
  2. map传入的起始位置是limit关键字 需要查询返回的第start~end条数据的起始数;
  3. 设置默认起始页为首页,设置每页显示件数,根据抽出 的所有数据计算totalPage(总页数),
  4. 总页数 = 总件数%页面件数 == 0 ?总件数/页面件数 :总件数/页面件数+1;
  5. totalPage总页数取得后,所需跳转页数与总页数判断,确保startIndex不会越界;
  6. 查询完结果后 将totalPage和 查询出的 数据一并返回至视图解析器
  7. 前端根据查询的数据进行显示,根据totalPage进行页码编辑;

经上述思路分析,不如PageHelper!!!

方式二:RowBounds分页(不推荐使用)

我们除了使用Limit在SQL层面实现分页,也可以使用RowBounds在Java代码层面实现分页,当然此种方式作为了解即可。

因为各方面问题,甚至于官方也不推荐。

  • 性能问题
  • 不适合复杂查询
  • 缺乏灵活性
  • 兼容性差

建立高效、稳定的数据库访问层才是持久层DB交互最终需要考虑的!

步骤:

  1. mapper接口
//选择全部用户RowBounds实现分页
List<User> getUserByRowBounds();
  1. Mybatis文件
<select id="getUserByRowBounds" resultType="user">select * from user
</select>
  1. 测试类

在这里,我们需要使用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

了解即可,可以自己尝试使用

官方文档:https://pagehelper.github.io/

具体使用方法:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md

引入依赖
<!-- 引入 PageHelper 使用Springboot -->
<!-- <dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version> 
</dependency> 
--><!-- 如果你不使用 Spring Boot,使用SpringMVC可使用: -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.3.3</version>
</dependency>
<!-- 最新版 : -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>6.1.0</version>
</dependency>
配置plugins

Spring的配置和Mybatis的配置选一个就可以;

  1. Spring的配置

引入到SqlSessionFactoryBean中,使用Interceptor类型

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="configLocation" value="classpath:mybatis-config.xml"/><!--    导入pageHelper分页    --><property name="plugins"><array><bean class="com.github.pagehelper.PageInterceptor"><property name="properties"><value>helperDialect=mysqlreasonable=truesupportMethodsArguments=trueparams=count=countSqlautoRuntimeDialect=true</value></property></bean></array></property>
</bean>
  1. mybatis-config.xml
<configuration><!-- 插件配置:PageHelper 分页插件 --><plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"><property name="helperDialect" value="mysql"/><property name="reasonable" value="true"/><property name="supportMethodsArguments" value="true"/><property name="params" value="count=countSql"/></plugin></plugins></configuration>
使用 PageHelper 进行分页查询
  1. Service层实现代码逻辑
@Override
public PageInfo<User> getUserList(int pageNum, int pageSize) {// 开始分页:第 pageNum 页,每页 pageSize 条PageHelper.startPage(pageNum, pageSize);// 执行查询(这个查询会被自动分页)List<User> users = userMapper.getUserList();// 封装成 PageInfo 对象,包含分页信息PageInfo<User> pageInfo = new PageInfo<>(users);System.out.println("pageInfo {}:" + pageInfo);return pageInfo;
}
  1. Controller层代码实现逻辑
    1. 返回JSON,前端使用Ajax处理
@RequestMapping("/getUserList")
@ResponseBody
public Object getUserList( @RequestParam(defaultValue = "1") int pageNum,@RequestParam(defaultValue = "10") int pageSize) {PageInfo<User> pageInfo  = userService.getUserList(pageNum,pageSize);return  ResponseEntity.ok(pageInfo);
}
2. 返回视图解析的网站地址,使用`JSP`显示`ModelView`的数据
@RequestMapping("/getUserList")
public Object getUserList( Model model,@RequestParam(defaultValue = "1") int pageNum,@RequestParam(defaultValue = "10") int pageSize) {PageInfo<User> pageInfo  = userService.getUserList(pageNum,pageSize);model.addAttribute("pageInfo",pageInfo);model.addAttribute("userList",pageInfo.getList());model.addAttribute("currentPage", pageInfo.getPageNum());model.addAttribute("totalPages", pageInfo.getPages());model.addAttribute("pageSize", pageInfo.getPageSize());return "userList";
}
  1. 前端页面显示
    1. JSP显示
<c:if test="${currentPage > 1}">
<a href="?pageNum=${currentPage - 1}&pageSize=${pageSize}">上一页</a>
</c:if><span> 第 ${currentPage} 页,共 ${totalPages}</span><c:if test="${currentPage < totalPages}">
<a href="?pageNum=${currentPage + 1}&pageSize=${pageSize}">下一页</a>
</c:if>
配合`set`标签使用,明细显示行号
<%--  计算当前行的编号--%>
<c:set var="index"  value="${(currentPage - 1) * pageSize + status.index}" />
<tbody>
<c:forEach items="${userList}" var="user" varStatus="status">
<%--  计算当前行的编号--%>
<c:set var="index"  value="${(currentPage - 1) * pageSize + status.index}" /><tr>
<td>${index+1}</td>
<td>${user.userCode}</td>
<td>${user.userName}</td>
<td>${user.gender}</td>
<td>${user.phone}</td>
<td>${user.address}</td>
<td>
<a class="btn btn-primary" href="/user/modifyUser?id=${user.id}">修改</a>
<a class="btn btn-danger" href="/user/deleteUser?id=${user.id}">删除</a>
<a class="btn btn-success" href="/user/viewUser?id=${user.id}">查看</a>
</td>
</c:forEach>
</tbody>
页面显示如下
  1. 第一页
  2. 第二页
优化分页内容显示
  1. 使用BootStarp的式样导入,

使用pagination显示叠加样式;

除了pagination 还有pager

  1. 增加 循环遍历显示页数 ,根据页码指定跳转式样

思路:

1. foreach遍历条数,起始:1,结束:总页数;
2. 当前页高亮显示,其他页默认显示

效果如下:

页面显示效果:

http://www.dtcms.com/a/311479.html

相关文章:

  • Elasticsearch 混合检索一句 `retriever.rrf`,把语义召回与关键词召回融合到极致
  • 模拟激光相机工作站版本6.0 5.2.32 6.0.44 6.031 5.2.20
  • 题解:P4447 [AHOI2018初中组] 分组
  • 归并排序(简单讲解)
  • [论文阅读] 人工智能 + 软件工程 | GitHub Marketplace中CI Actions的功能冗余与演化规律研究
  • 【RK3568 看门狗驱动开发详解】
  • Kubernetes Gateway API 详解:现代流量路由管理方案
  • 【最后203篇系列】030 强化学习探索
  • 浏览器及java读取ros1的topic
  • 重生之我在暑假学习微服务第八天《OpenFeign篇》
  • 暑期算法训练.13
  • cv弹窗,退款确认弹窗
  • 数据结构(12)二叉树
  • 深入 Go 底层原理(六):垃圾回收(GC)
  • 数据资产是什么?
  • MySQL 内置函数
  • npm安装下载慢问题
  • 离线安装docker和docker-compose
  • 【人工智能agent】--服务器部署PaddleX 的 印章文本识别模型
  • JVM 调优中JVM的参数如何起到调优动作?具体案例,G1GC垃圾收集器参数调整建议
  • Junit5+Maven+RestAssured+Allure接口自动化框架
  • VScode对Ubuntu用root账号进行SSH远程连接开发
  • MSQL-聚簇索引与非聚簇索引的比较
  • k8s的pod的YAML问题
  • 公共卫生场景下漏检率↓76%:陌讯动态特征融合算法在口罩识别中的实战解析
  • 7月销售超5万辆,零跑汽车再创单月历史新高
  • 开源列式分布式数据库clickhouse
  • SpringBoot 启动富文本文字更改
  • .NET 中,Process.Responding 属性用于检查进程的用户界面是否正在响应
  • Linux性能监控与调优全攻略