【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语法更能降低理解难度。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
3月前
|
SQL Java 数据库连接
MyBatis 的映射关系
MyBatis 核心功能之一是映射关系,支持一对一、一对多和多对多三种 ORM 映射。通过实体类与配置文件结合,开发者可灵活实现数据关联,提升数据库操作效率。
276 4
|
7月前
|
SQL XML Java
菜鸟之路Day35一一Mybatis之XML映射与动态SQL
本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`&lt;if&gt;`、`&lt;where&gt;`、`&lt;set&gt;`、`&lt;foreach&gt;`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`&lt;sql&gt;`和`&lt;include&gt;`实现代码复用,优化维护效率。
643 5
|
9月前
|
SQL XML Java
七、MyBatis自定义映射resultMap
七、MyBatis自定义映射resultMap
262 6
|
9月前
|
Java 数据库连接 mybatis
MyBatis篇-映射关系(1-1 1-n n-n)
本文介绍了MyBatis中四种常见关系映射的配置方法,包括一对一、一对多、多对一和多对多。**一对一**通过`resultMap`实现属性与字段的映射;**一对多**以用户-角色为例,使用`&lt;collection&gt;`标签关联集合数据;**多对一**以作者-博客为例,利用`&lt;association&gt;`实现关联;**多对多**则通过引入第三方类(如UserForDept)分别在User和Dept类中添加集合属性,并配置对应的`&lt;collection&gt;`标签完成映射。这些方法解决了复杂数据关系的处理问题,提升了开发效率。
|
XML Java 数据库连接
Mybatis映射关系
简介:本文介绍了MyBatis框架中四种常见的关系映射方式,包括一对一、一对多、多对一及多对多。一对一通过简单属性映射实现;一对多通过在主对象中添加集合属性并使用`&lt;collection&gt;`标签映射子对象集合;多对一则利用`&lt;association&gt;`标签在主对象中映射单个子对象;多对多需引入第三方类,分别在两个主对象中添加对方的集合属性,并通过`&lt;collection&gt;`标签实现映射。
232 32
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
SQL Java 数据库连接
mybatis如何实现分页查询?
【10月更文挑战第19天】mybatis如何实现分页查询?
1178 3
|
6月前
|
Java 数据库连接 数据库
Spring boot 使用mybatis generator 自动生成代码插件
本文介绍了在Spring Boot项目中使用MyBatis Generator插件自动生成代码的详细步骤。首先创建一个新的Spring Boot项目,接着引入MyBatis Generator插件并配置`pom.xml`文件。然后删除默认的`application.properties`文件,创建`application.yml`进行相关配置,如设置Mapper路径和实体类包名。重点在于配置`generatorConfig.xml`文件,包括数据库驱动、连接信息、生成模型、映射文件及DAO的包名和位置。最后通过IDE配置运行插件生成代码,并在主类添加`@MapperScan`注解完成整合
1109 1
Spring boot 使用mybatis generator 自动生成代码插件
|
9月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
726 0