最全面的Mybatis教程,从“开局”到“通关”(一)

前言

在这里插入图片描述

大学生

本文为SSM框架 【Mybatis】 相关知识,MyBatis 是一款优秀的半自动的ORM持久层框架,下边将对Mybatis的简介Mybatis的CRUD实现Mybatis的配置文件Mybatis的日志配置resultMap详解分页实现注解式开发Lombok的使用关联映射动态SQLMybatis缓存等进行详尽介绍~
🚩 Are you ready❓ Let’s Go ❗️

封装性

📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)

求职招聘


目录

原神人物动画

SSM框架 【Mybatis】(一)

jdk动态代理

在这里插入图片描述

随身wifi

一、Mybatis简介

1️⃣什么是Mybatis

  • MyBatis 本是apache的一个开源项目【iBatis】;2010年这个项目由apache software foundation(Apache软件基金会) 迁移到了google code(谷歌的代码托管平台),并且改名为MyBatis;2013年11月迁移到Github。
  • MyBatis是一款优秀的持久层框架
  • MyBatis支持定制SQL、存储过程以及高级映射
  • Mybatis避免了几乎所有的JDBC代码和手动设置参数,以及获取结果集
  • Mybatis可以使用简单的XML或注解来配置和映射原生类型、接口和Java的POJO(Plain Old Java Objects,普通老式Java对象)为数据库中的记录

Mybatis的Maven仓库下载地址: https://mvnrepository.com/artifact/org.mybatis/mybatis
Mybatis的GitHub地址: https://github.com/mybatis/mybatis-3/releases
Mybatis的中文文档地址: https://mybatis.org/mybatis-3/zh/index.html

Spring Boot

2️⃣持久化

持久化是将程序数据在持久状态和瞬时状态间转换的机制。通俗的讲,就是瞬时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)。

ai

  • 程序产生的数据首先都是在内存。
  • 内存是不可靠的,他丫的一断电数据就没了。
  • 那可靠的存储地方是哪里?硬盘、U盘、光盘等。
  • 我们的程序在运行时说的持久化通常就是指将内存的数据存在硬盘。

3️⃣持久层

对于分层的概念我们知道:

容器

  • 业务是需要操作数据的
  • 数据是在磁盘上的
  • 具体业务调用具体的数据库操作,耦合度太高,复用性太差
  • 将操作数据库的代码统一抽离出来,自然就形成了介于业务层和数据库中间的独立的层

持久层的工作:

变粉色

  • 完成持久化工作的代码块
  • 层之间的界限非常明显

4️⃣聊聊ORM

ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法。

Tank

  • jpa(Java Persistence API)是java持久化规范,是orm框架的标准,主流orm框架都实现了这个标准。
  • hibernate: 全自动的框架,强大、复杂、笨重、学习成本较高,不够灵活,实现了jpa规范。Java Persistence API(Java 持久层 API)
  • MyBatis: 半自动的框架(懂数据库的人 才能操作) 必须要自己写sql,不是依照的jpa规范实现的。

很多人青睐 MyBatis ,原因是其提供了便利的 SQL 操作,自由度高,封装性好…… JPA对复杂 SQL 的支持不好,没有实体关联的两个表要做 join 的确要花不少功夫。

多线程

5️⃣MyBatis的优点和缺点

sql语句与代码分离,存放于xml配置文件中:

DataX 使用介绍

  • 优点:便于维护管理,不用在java代码中找这些语句;
  • 缺点:JDBC方式可以用打断点的方式调试,但是MyBatis调试比较复杂,一般要通过log4j日志输出日志信息帮助调试,然后在配置文件中修改。

用逻辑标签控制动态SQL的拼接:

ferry

  • 优点:用标签代替编写逻辑代码;
  • 缺点:拼接复杂SQL语句时,没有代码灵活,拼写比较复杂。不要使用变通的手段来应对这种复杂的语句。

查询的结果集与java对象自动映射:

硬件

  • 优点:保证名称相同,配置好映射关系即可自动映射或者,不配置映射关系,通过配置列名=字段名也可完成自动映射。
  • 缺点:对开发人员所写的SQL依赖很强。

编写原生SQL:

微信授权

  • 优点:接近JDBC,比较灵活。
  • 缺点:对SQL语句依赖程度很高;并且属于半自动,数据库移植比较麻烦,比如MySQL数据库编程Oracle数据库,部分的SQL语句需要调整。

最重要的一点,使用的人多!公司需要!

仿真

二、第一个MyBatis程序

实现步骤:搭建环境—>导入MyBatis—>编写相关代码—>测试

语音克隆

1️⃣搭建环境

🍀(1)搭建数据库

万兆

   -- 创建数据库
   create database `mybatis`;
   use mybatis;
   -- 创建表
   create table `user`(
      `id` int(20) not null,
      `name` varchar(30) default null,
      `pwd` varchar(30) default null,
      primary key(`id`) 
   )engine=InnoDB default charset=utf8mb4;
   -- 插入数据
   insert into `user`(`id`,`name`,`pwd`) values
  (1,'张三','123'),
  (2,'李四','123'),
  (3,'王五','123');

🍀(2)新建一个普通maven项目作为父项目,并导入sql驱动,mybatis,junit组件

ethers

  <!--导入依赖-->
  <dependencies>
      <!--mysql驱动-->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.46</version>
      </dependency>
      <!--Mybatis-->
      <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.5.2</version>
      </dependency>
      <!--junit-->
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
      </dependency>
  </dependencies>

🍀(3)新建一个新组件作为子级项目,普通maven的module

创建文件

🍀(4)添加配置文件

SQL性能优化

  • 在src->main->resources目录下新建mybatis-config.xml文件,把官方的配置代码复制粘贴(不能在配置文件中写中文注释)
  • 配置文件的作用就是连接数据库
  <?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>
    <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}"/> //数据库名字,默认root
          <property name="password" value="${password}"/> //数据库密码,自己的数据库密码,一般为root
        </dataSource>
      </environment>
    </environments>
  </configuration>

2️⃣编写mybatis工具类

MybatisUtils.java:

搜狗

  //SqlSessionFactory --生产--> SqlSession
  public class MybatisUtils {
      private static SqlSessionFactory sqlSessionFactory; //提升作用域
      //获取工厂,固定代码
      static {
          try {
              String resource="mybatis-config.xml";
              InputStream inputStream = Resources.getResourceAsStream(resource);
              sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
      //获取sqlSession
      //SqlSession完全包含了面向对象数据库执行SQL命令所需的方法
      public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession();}
  }

3️⃣编写相关代码

🍀(1)实体类

batch命令

  public class User {
      private int id;
      private String name;
      private String pwd;
      public User() { }
      public User(int id, String name, String pwd) {
          this.id = id;
          this.name = name;
          this.pwd = pwd;
      }
      public int getId() {
          return id;
      }
      public void setId(int id) {
          this.id = id;
      }
      public String getName() {
          return name;
      }
      public void setName(String name) {
          this.name = name;
      }
      public String getPwd() {
          return pwd;
      }
      public void setPwd(String pwd) {
          this.pwd = pwd;
      }
      @Override
      public String toString() {
          return "User{" +
                  "id=" + id +
                  ", name='" + name + '\'' +
                  ", pwd='" + pwd + '\'' +
                  '}';
      }
  }

🍀(2)Dao接口

零基础

  public interface UserDao {
      List<User> getUserList();
  }

🍀(3)xxxMapper.xml配置文件

Unity 运动曲线

  • 接口的实现类要改为以xxxMapper.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">
  <!--namespace:命名空间,绑定mapper/Dao接口-->
  <mapper namespace="com.wang.dao.UserDao">
  <!--id:接口的方法,resultType:接口的返回值类型-->
      <select id="getUserList" resultType="com.wang.pojo.User">
          select * from mybatis.user where id = #{id}
      </select>
  </mapper>

每一个Mapper.xml文件都需要在src->main->resources目录下的mybatis-config.xml核心配置文件中注册:

分支

<mappers>
  <mapper resource="com/wang/dao/UserMapper.xml">
</mappers>

4️⃣测试

  public class UserDaoTest {
      @Test
      public void test(){
          //获取SqlSession对象
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          //获取mapper
          UserDao mapper = sqlSession.getMapper(UserDao.class);
          List<User> list = mapper.getUserList();
          for (User u:list){
              System.out.println(u);
          }
          //不推荐使用以下方式
          /*
          这种方式能够正常工作,对使用旧版本 MyBatis 的用户来说也比较熟悉。但现在有了一种更简洁的方    式——使用和指定语句的参数和返回值相匹配的接口(比如 BlogMapper.class),现在你的代码不仅更清晰,更加 类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。
          */
          // List<User> list =  sqlSession.selectList("com.qian.dao.UserDao.getUserList");
          // for (User user : list) {
          //     System.out.println(user);
          // }
          
          //关闭SqlSession
          sqlSession.close();
      }
  }

三、使用Mybatis实现CRUD

1️⃣Mapper接口

public interface UserMapper {
    //查询全部用户
    List<User> getUserList();
    //根据id查询用户
    User getUserById(int id);
    //增加新的用户
    boolean insertNewUser(User u);
    //删除用户
    boolean deleteUserById(int id);
    boolean deleteUserByName(String name);
    //修改用户
    boolean updateUserById(User u);
}

2️⃣xxxMapper.xml文件

<?xml version="1.0" encoding="utf8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:命名空间,绑定mapper/Dao接口-->
<!--id:接口的方法,resultType:接口的返回值类型-->
<mapper namespace="com.wang.dao.UserMapper">
    <select id="getUserList" resultType="com.wang.pojo.User">
        select * from mybatis.user
    </select>
    <select id="getUserById" parameterType="int" resultType="com.wang.pojo.User">
        select * from mybatis.user where id=#{id}
    </select>
    <!-- 对象中的属性,可以直接取出来用 -->
    <insert id="insertNewUser" parameterType="com.wang.pojo.User">
        insert into mybatis.user (id, name, pwd) VALUES (#{id},#{name},#{pwd})
    </insert>
    <delete id="deleteUserById" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>
    <delete id="deleteUserByName" parameterType="String">
        delete from mybatis.user where name=#{name}
    </delete>
    <update id="updateUserById" parameterType="com.wang.pojo.User">
        update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
    </update>
</mapper>

3️⃣测试类

public class UserDaoTest {
    @Test
    public void test(){
        //获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        try{
            //获取mapper
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            
            // 查询全表
            List<User> list = mapper.getUserList();
            for (User u:list){
                System.out.println(u);
            }
            
            //根据id查询
            User user = mapper.getUserById(1);
            System.out.println(user);
            
            //插入新用户,注意:更新,插入,删除都需要提交事务
            User user1 = new User(4,"李四","25615");
            boolean isInserted = mapper.insertNewUser(user1);
            sqlSession.commit();
            //代码优化
            if (mapper.insertNewUser(new User(4,"李四","25615"))) sqlSession.commit();
            
            //删除用户
            if (mapper.deleteUserById(4))sqlSession.commit();
            if (mapper.deleteUserByName("李四"))sqlSession.commit();
            
            //修改用户
            if (mapper.updateUserById(new User(4,"王五","6849816")))sqlSession.commit();
            
        }finally {
            //关闭SqlSession
            sqlSession.close();
        }
    }
}

4️⃣Map的使用

map可以代替任何的实体类,所以当我们数据比较复杂时,可以适当考虑使用map来完成相关工作。
🍀(1)写方法

kafka3.0

UserMapper.java:

Opencv傅里叶变换

  User getUser(Map<String,Object> map);
  boolean addUser(Map<String,Object> map);

🍀(2)写sql

回归预测

UserMapper.xml:

  <select id="getUser" parameterType="map" resultType="com.qian.pojo.User">
      select * from mybatis.user where id=#{userId}
  </select>
  <insert id="addUser" parameterType="map">
      insert into mybatis.user (id, name, pwd) VALUES (#{userId},#{userName},#{password})
  </insert>

🍀(3)测试

Test.java:

  @Test
  public void test(){
      //获取SqlSession对象
      SqlSession sqlSession = MybatisUtils.getSqlSession();
      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("userId",5);
      User user = mapper.getUser(map);
      System.out.println(user);
      map.put("userId",5);
      map.put("userName","孙悟空");
      map.put("password","123456");
      if (mapper.addUser(map)) sqlSession.commit();
      sqlSession.close();
  }

5️⃣模糊查询

🍀方案一:在Java代码中拼串

Test.java:

string name = "%IT%";
list<name> names = mapper.getUserByName(name);

UserMapper.xml:

<select id= "getUsersByName">
	select * from user where name like #{name}
</select>

🍀方案二:在配置文件中拼接1

Test.java:

string name = "IT";
list<User> users = mapper.getUserByName(name);

UserMapper.xml:

<select id= "getUsersByName">
    select * from user where name like "%"#{name}"%"
</select>

🍀方案三:在配置文件中拼接2

Test.java:

string name = "IT";
list<User> users = mapper.getUserByName(name);

UserMapper.xml:

<select id= "getUsersByName">
    select * from user where name like "%${name}%"
</select>

四、Mybatis配置文件

1️⃣ 核心配置文件

核心配置文件mybatis-config.xml包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文件的层次结构如下(顺序不能乱):

1.properties是一个配置属性的元素
2.settings设置,mybatis最为复杂的配置也是最重要的,会改变mybatis运行时候的行为
3.typeAliases别名(在TypeAliasRegistry中可以看到mybatis提供了许多的系统别名)
4.typeHandlers 类型处理器(比如在预处理语句中设置一个参数或者从结果集中获取一个参数时候,都会用到类型处理器,在TypeHandlerRegistry中定义了很多的类型处理器)
5.objectFactory 对象工厂(myabtis在构建一个结果返回的时候,会使用一个ObjectFactory去构建pojo)
6.plugins 插件
7.environments 环境变量
    environment 环境变量
       transactionManager 事务管理器
       dataSource 数据源
       databaseIdProvider 数据库厂商标识
8.mappers 映射器

下面针对几个重要的元素environments,properties,mappers,typeAliases,settings进行讲解。

2️⃣environments(环境)

environments可以为mybatis配置多环境运行,将SQL映射到多个不同的数据库上,必须指定其中一个为默认运行环境(通过default指定),如果想切换环境修改default的值即可。

最常见的就是,生产环境和开发环境,两个环境切换必将导致数据库的切换。

<environments default="development">
 <environment id="development">
   <transactionManager type="JDBC">
     <property name="..." value="..."/>
   </transactionManager>
   <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>
    
  <environment id="product">
       <transactionManager type="JDBC">
         <property name="..." value="..."/>
       </transactionManager>
       <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>
  • dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
  • 数据源是必须配置的。有三种内建的数据源类型:
type="[UNPOOLED|POOLED|JNDI]")
 - unpooled:这个数据源的实现只是每次被请求时打开和关闭连接。
 - pooled:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来 , 这是一种使得并发 Web 应用快速响应请求的流行处理方式。
 - jndi:这个数据源的实现是为了能在如 Spring 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
  • 数据源也有很多第三方的实现,比如druid,hikari,dbcp,c3p0等等…
  • 具体的一套环境,通过设置id进行区别,id保证唯一!
  • 子元素节点:transactionManager – [ 事务管理器 ](以下两种事务管理器类型都不需要设置任何属性)
<!-- 语法 -->
<transactionManager type="[ JDBC | MANAGED ]"/>
  • 子元素节点:数据源(dataSource)

3️⃣properties(属性)

数据库连接信息我们最好放在一个单独的文件中。

🍀(1)在资源目录下新建一个db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=root

🍀(2)将db.properties文件导入核心配置文件

<configuration>
   <!--导入properties文件-->
   <properties resource="db.properties"/>

   <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>
</configuration>

4️⃣mappers(映射器)

mappers的存在就是要对写好的mapper和xml进行统一管理,要不然系统怎么知道我们写了哪些mapper。

🍀(1)常用引入方式

<mappers>
    <!-- 使用相对于类路径的资源引用 -->
    <mapper resource="com/wan/dao/userMapper.xml"/>
    <!-- 面向注解时使用全类名 -->
    <mapper class="com.wang.dao.AdminMapper"/>
</mappers>

🍀(2)在Mapper文件里进行绑定

<?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="com.wang.mapper.UserMapper">
   
</mapper>

namespace中文意思:命名空间,作用是namespace的命名必须跟某个接口同名,这才能找到实现绑定。

5️⃣typeAliases(类型别名)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

在mybatis-config.xml -> configuration进行配置:

  <typeAliases>
      <typeAlias type="com.wang.pojo.User" alias="user"></typeAlias>
      <!-- 另一种方式:直接扫描一个包目录下的 -->
      <package name="com.wang.pojo"/>
  </typeAliases>
  • 配置以后xxxMapper.xml的返回值(resultType)就可以替换为resultType user
  • 实体类较少的时候使用第一种,较多就直接扫描包目录
  • 第二种也可以用注解@Alias(“xxx”)给类起别名

6️⃣settings(设置)

settings能对我的一些核心功能进行配置,如懒加载、日志实现、缓存开启关闭等。

简单参数说明:

参数 描述 有效值 默认值
cacheEnabled 该配置影响的所有映射器中配置的缓存的全局开关。 true /false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 true / false false
useColumnLabel 使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 true / false true
useGeneratedKeys 允许 JDBC 支持自动生成主键,需要驱动兼容。如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 true / false False
defaultStatementTimeout 设置超时时间,它决定驱动等待数据库响应的秒数。 Any positive integer Not Set (null)
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 true / false False
logPrefix 指定 MyBatis 增加到日志名称的前缀。 Any String Not set
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J / LOG4J / LOG4J2 / JDK_LOGGING / COMMONS_LOGGING / STDOUT_LOGGING / NO_LOGGING Not set

完整的 settings 元素,有很多可以配置的选项(可以自行了解):

<settings>
    <!---->
     <setting name="cacheEnabled" value="true"/>
    <!---->
     <setting name="lazyLoadingEnabled" value="true"/>
    <!---->
     <setting name="multipleResultSetsEnabled" value="true"/>
     <setting name="useColumnLabel" value="true"/>
     <setting name="useGeneratedKeys" value="false"/>
     <setting name="autoMappingBehavior" value="PARTIAL"/>
     <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
     <setting name="defaultExecutorType" value="SIMPLE"/>
     <setting name="defaultStatementTimeout" value="25"/>
     <setting name="defaultFetchSize" value="100"/>
     <setting name="safeRowBoundsEnabled" value="false"/>
     <setting name="mapUnderscoreToCamelCase" value="false"/>
     <setting name="localCacheScope" value="SESSION"/>
     <setting name="jdbcTypeForNull" value="OTHER"/>
     <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

五、Mybatis日志配置

配置日志的一个重要原因是想在调试的时候能观察到sql语句的输出,能查看中间过程

1️⃣标准日志实现

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

 <configuration>
      <properties resource="db.properties"/>
      <settings>
          <setting name="logImpl" value="STDOUT_LOGGING"/>
      </settings>
      ... ...
  <configuration>

2️⃣组合logback完成日志功能

🍀(1)导入log4j的包

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
</dependency>

🍀(2)log4j.properties配置文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} %c [%thread] %-5level %msg%n"/>
    <property name="log_dir" value="d:/logs" />

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <appender name="file" class="ch.qos.logback.core.FileAppender">
        <!--日志格式配置-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
        <!--日志输出路径-->
        <file>${log_dir}/sql.log</file>
    </appender>

    <root level="ALL">
        <appender-ref ref="console"/>
    </root>

    <logger name="mybatis.sql" level="debug" additivity="false">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </logger>

</configuration>

🍀(3)setting设置日志实现

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

六、resultMap详解

如果数据库字段和实体的字段是一一对应,那么MyBatis会【自动映射】,但是如果不一致,比如一个叫user一个叫username,那么就需要我们手动的建立一一映射的关系了。

🍀(1)Java实体类

public class User {

   private int id;  		    //id
   private String name;   		//姓名,数据库为username
   private String password;     //密码,一致
   
   //构造
   //set/get
   //toString()
}

🍀(2)mapper接口

//根据id查询用户
User selectUserById(int id);

🍀(3)mapper映射文件

<select id="selectUserById" resultType="user">
  select * from user where id = #{id}
</select>

🍀(4)测试与结果分析

Test.java:

@Test
public void testSelectUserById() {
   UserMapper mapper = session.getMapper(UserMapper.class);
   User user = mapper.selectUserById(1);
   System.out.println(user);
   session.close();
}

结果:

User{id=1, name='null', password='123'}

查询出来发现 name为空 . 说明出现了问题!

分析:

  • select * from user where id = #{id} 可以看做select id,username,password from user where id = #{id}
  • mybatis会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写) , 利用反射去对应的实体类中查找相应列名的set方法设值,当然找不到username

解决方案:

方案一:为列名指定别名 , 别名和java实体类的属性名一致 。

<select id="selectUserById" resultType="User">
  select id , username as name ,password from user where id = #{id}
</select>

方案二:使用结果集映射->ResultMap 【推荐】

<resultMap id="UserMap" type="User">
   <!-- id为主键 -->
   <id column="id" property="id"/>
   <!-- column是数据库表的列名 , property是对应实体类的属性名 -->
   <result column="username" property="name"/>
   <result column="password" property="password"/>
</resultMap>

<select id="selectUserById" resultMap="UserMap">
  select id , username , password from user where id = #{id}
</select>

结论:

这个地方我们手动调整了映射关系,称之为【手动映射】。但如果不调整呢? MyBatis当然会按照约定自动映射。
当然约定的最基本的操作就是全部都一样,还有就是下划线和驼峰命名的自动转化。

<settings>
    <!--开启驼峰命名规则-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

后记

在这里插入图片描述
↪️本文下接:最全面的Mybatis教程,从“开局”到“通关”(二)
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注