【MyBatis学习笔记 三】结果集映射、日志处理及分页查询

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【MyBatis学习笔记 三】结果集映射、日志处理及分页查询

上一篇Blog了解了基本的MyBatis操作后,我们本篇来学习一下如何实现一些较为高级的操作。分别是返回值的模型映射、日志处理以及分页查询的实现。

模型映射

如果是一个初始化的项目,我们当然尽量的让我们的数据对象,也就是Data Model和数据表中的字段名称保持一致,但是要维护一些老的项目或者说确实有一些我们认为名称应该有所区别的,就需要做一个映射了,类似Hibernate里的Person.hbm.xml文件,我们的Mapper文件也需要做返回结果的映射。

命名不一致的问题

首先我们在上篇【MyBatis学习笔记 二】MyBatis基本操作及配置解析 Blog的基础上继续做处理,我们在库内增加一个字段:hobby,兴趣爱好,并给两个字段设置值:

同时给我们的类Person增加属性,但是命名为interests

package com.example.MyBatis.dao.model;
import lombok.Data;
/*
 * person表对应对象
 * */
@Data
public class Person {
    private int id;
    private String username;
    private String password;
    private int age;
    private int phone;
    private String email;
    private String interests;
}

接下来在我们的处理方法中进行查询:

<select id="getPersonList" resultType="com.example.MyBatis.dao.model.Person">
        select * from person
    </select>

通过测试类进行测试:

@Test
    public void test(){
        //1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //2.执行SQL
        PersonDao personDao = sqlSession.getMapper(PersonDao.class);
        List<Person> personList = personDao.getPersonList();
        for (Person person : personList) {
            System.out.println(person);
        }
        //关闭sqlSession
        sqlSession.close();
    }

返回结果如下:

可以看到由于字段名不对称,无法获取,mybatis会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写) , 去对应的实体类中查找相应列名的set方法设值 , 由于找不到interests的set方法, 所以返回null。我们调整查询语句如下:

<select id="getPersonList" resultType="com.example.MyBatis.dao.model.Person">
        select username,password,age,phone,email,hobby as interests  from person
    </select>

通过hobby as interests 设置别名,确定返回属性为interests,然后再去找对应的set方法就可以了:

使用ResultMap解决

通过设置别名的方式确实可以解决,但是每个方法都需要设置,如果不一致的字段多还需要写大量冗余的sql代码,所以使用ResultMap手动映射来解决这个问题更好。它相当于数据表字段和模型直接的一个映射关系配置:

<!-- id确定返回map, type为模型全类名 -->
    <resultMap id="PersonMap" type="com.example.MyBatis.dao.model.Person">
        <!-- id为主键 -->
        <id column="id" property="id"/>
        <!-- column写错会因为查到数据匹配不上,给默认值, type写错会报错,找不到属性-->
        <result column="age" property="age"/>
        <!-- column是数据库表的列名 , property是对应实体类的属性名 -->
        <result column="hobby" property="interests"/>
    </resultMap>
    <select id="getPersonList" resultMap="PersonMap">
        select * from person
    </select>

以上我们可以发现,其实不写所有的属性也可以,也就是优先走配置,如果配置没有,还是会走自动映射去找属性的,所以对于命名一致的数据字段和类的属性就无需再加了

但是为了规范和不易出错,我们最好把对应关系都写全了,这样也能对全表字段有正确认知:

<!-- id确定返回map, type为模型全类名 -->
    <resultMap id="PersonMap" type="com.example.MyBatis.dao.model.Person">
        <!-- id为主键 -->
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="password" property="password"/>
        <result column="age" property="age"/>
        <result column="phone" property="phone"/>
        <!-- column写错会因为查到数据匹配不上,给默认值, type写错会报错,找不到属性-->
        <result column="email" property="email"/>
        <!-- column是数据库表的列名 , property是对应实体类的属性名 -->
        <result column="hobby" property="interests"/>
    </resultMap>
     <!--注意返回类型是resultMap而不是resultType -->
    <select id="getPersonList" resultMap="PersonMap">
        select * from person
    </select>

日志处理

如果一个数据库相关的操作出现了问题,我们可以根据输出的SQL语句快速排查问题。对于以往的开发过程,我们会经常使用到debug模式来调节,跟踪我们的代码执行过程。但是现在使用Mybatis是基于接口,配置文件的源代码通过反射执行,我们无法debug。因此,我们必须选择日志工具来作为我们开发,调节程序的工具。

日志工具分类

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

1. SLF4J
 2. Apache Commons Logging
 3. Log4j-2
 4. Log4j
 5. JDK logging

具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会按优先级使用最先找到的,如果一个都未找到,日志功能就会被禁用。我们可以通过核心配置文件mybatis-config.xml进行日志配置【注意settings节点顺序】:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>
    <!--导入properties文件-->
    <properties resource="properties/db.properties"/>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mappers/personMapper.xml"/>
    </mappers>
</configuration>

然后我们再执行单元测试就可以看到打印出日志记录了:

使用Log4j进行日志处理

什么是Log4j?Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件;可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程;可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

1 导入Log4j的Maven依赖

在pom.xml中导入日志依赖,在maven中搜索到然后选择最新版本号:

导入方式如下:

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

2 配置log4j.properties文件

在resources下配置文件:log4j.properties,只要是该目录下即可:

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
# 设置日志输出级别以及输出目的地,可以设置多个输出目的地,开发环境下,日志级别要设置成DEBUG或者ERROR
# 前面写日志级别,逗号后面写输出目的地
# log4j.rootLogger = [level],appenderName1,appenderName2,…
log4j.rootLogger=Debug,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 输出到控制台
log4j.appender.console.Target = System.out
# 指定控制台输出日志级别
log4j.appender.console.Threshold=DEBUG
# 默认值是 true, 表示是否立即输出
log4j.appender.console.ImmediateFlush = true
# 设置编码方式
log4j.appender.console.Encoding = UTF-8
# 日志输出布局
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 如果日志输出布局为PatternLayout 自定义级别,需要使用ConversionPattern指定输出格式
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
# 指定输出文件路径
log4j.appender.file.File=./log/tml.log
# 指定单个日志文件最大值
log4j.appender.file.MaxFileSize=10mb
# 指定输出日志级别
log4j.appender.file.Threshold=DEBUG
# 默认值是 true, 表示是否立即输出
log4j.appender.file.ImmediateFlush = true
# 设置编码方式
log4j.appender.file.Encoding = UTF-8
# 日志输出布局
log4j.appender.file.layout=org.apache.log4j.PatternLayout
# 如果日志输出布局为PatternLayout 自定义级别,需要使用ConversionPattern指定输出格式
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.sq1.PreparedStatement=DEBUG

DEBUG指的是日志输出级别,一共有 7 个级别(OFF、 FATAL、 ERROR、 WARN、 INFO、 DEBUG、 ALL),一般常用的日志输出级别分别为 DEBUG、 INFO、 ERROR 以及 WARN,分别表示 “调试级别”、 “标准信息级别”、 “错误级别”、 “异常级别”

  • 如果需要查看程序运行的详细步骤信息,一般选择 “DEBUG” 级别,因为该级别在程序运行期间,会在控制台才打印出底层的运行信息,以及在程序中使用 Log 对象打印出调试信息。
  • 如果是日常的运行,选择 INFO 级别,该级别会在控制台打印出程序运行的主要步骤信息
  • ERRORWARN级别分别代表 不影响程序运行的错误事件潜在的错误情形

3 测试类查看日志输出

引入org.apache.log4j.Logger日志包,进行测试:

//注意导包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(PersonTest.class);
    @Test
    public void test(){
        logger.info("info:进入test方法");
        logger.debug("debug:进入test方法");
        logger.error("error: 进入test方法");
        //1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //2.执行SQL
        PersonDao personDao = sqlSession.getMapper(PersonDao.class);
        List<Person> personList = personDao.getPersonList();
        for (Person person : personList) {
            System.out.println(person);
        }
        //关闭sqlSession
        sqlSession.close();
    }

实现效果如下:

在本地日志文件中也可以看到:

分页查询

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

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

1 调整PersonDao接口定义

首先我们可以在PersonDao接口中增加一个方法getPersonListPage用来分页查找数据:

List<Person> getPersonListPage(Map<String,Integer> map);

2 编写personMapper.xml

其次依据PersonDao接口中增加的方法我们可以在personMapper中进行sql语句编写来实现:

<select id="getPersonListPage" parameterType="map" resultMap="PersonMap">
        select * from person limit #{startIndex},#{pageSize}
    </select>

3 编写单元测试实现

最后我们编写单元测试查看实现效果:

@Test
    public void testGetPersonListPage(){
        //1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //2.执行SQL
        PersonDao personDao = sqlSession.getMapper(PersonDao.class);
        int currentPage = 1;  //第几页
        int pageSize = 1;  //每页显示几个
        Map<String,Integer> map = new HashMap<>();
        map.put("startIndex",(currentPage-1)*pageSize);
        map.put("pageSize",pageSize);
        List<Person> personList = personDao.getPersonListPage(map);
        for (Person person : personList) {
            System.out.println(person);
        }
        //关闭sqlSession
        sqlSession.close();
    }

实现效果如下,获取到了第一页共一条数据:

总结一下

本篇Blog比较杂,主要了解了三部分内容:结果集的映射模型、日志处理以及分页查询这三种我们日常使用时的Mybatis实现方式,看来映射模型也是需要的,和Hibernate类似,现在看来最大的不同就是,Mybatis既运用了SQL的灵活又实现了对象的封装,而Hibernate则是对数据库语法SQL做了完全的封装,自己实现了HQL语句,那么其实比起自己封装的,使用原生的SQL语法更能降低理解难度。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
14天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
25天前
|
SQL Java 数据库连接
mybatis如何实现分页查询?
【10月更文挑战第19天】mybatis如何实现分页查询?
50 3
|
2月前
|
SQL XML Java
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
3月前
|
SQL Java 关系型数据库
SpringBoot 系列之 MyBatis输出SQL日志
这篇文章介绍了如何在SpringBoot项目中通过MyBatis配置输出SQL日志,具体方法是在`application.yml`或`application.properties`中设置MyBatis的日志实现为`org.apache.ibatis.logging.stdout.StdOutImpl`来直接在控制台打印SQL日志。
SpringBoot 系列之 MyBatis输出SQL日志
|
3月前
|
Java 数据库连接 数据库
后端框架的学习----mybatis框架(6、日志)
这篇文章介绍了如何在MyBatis框架中使用日志功能,包括配置MyBatis的日志实现、使用log4j作为日志工具,以及如何通过配置文件控制日志级别和输出格式。
|
4月前
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
91 3
|
4月前
|
SQL 监控 Java
IDEA插件-Mybatis Log Free日志替换
MyBatis Log Free 是一个免费的用于在 IntelliJ IDEA 中显示 MyBatis 日志的插件。它可以帮助您更方便地查看和分析 MyBatis 的 SQL 执行情况,以及定位潜在的性能问题,提高开发效率。
394 0
IDEA插件-Mybatis Log Free日志替换
|
4月前
|
Kubernetes 关系型数据库 流计算
实时计算 Flink版产品使用问题之如何解决Flink集群在nativeKubernetes部署方式下日志无法映射到宿主机并容易丢失的问题
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
若依修改,集成mybatisplus报错,若依集成mybatisplus,总是找不到映射是怎么回事只要是用mp的方法就找报,改成mybatisPlus配置一定要改
若依修改,集成mybatisplus报错,若依集成mybatisplus,总是找不到映射是怎么回事只要是用mp的方法就找报,改成mybatisPlus配置一定要改
|
13天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
121 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板