0%

Java|MyBatis学习

image-20210904132917911

1.初识MyBatis

MyBatis简介

  • MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO为数据库中的记录

如果获取MyBatis

  • maven添加依赖

    1
    2
    3
    4
    5
    6
    7
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
    </dependency>

持久层

  • 数据持久化:持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 数据持久化的方法有:数据库(jdbc),io文件持久化
  • 持久层即完成持久化工作的代码块

为什么需要Mybatis

  • 帮助程序将数据存入数据库中

  • 方便

  • 传统的JDBC代码太复杂,而Mybatis简化,自动化

  • 优点:

    • 简单易学
    • 灵活
    • sql和代码的分离,提高了可维护性,支持对象与数据库字段的关系映射
    • 提供映射标签
    • 提供对象关系映射标签,支持对象关系组建维护
    • 通过xml标签,支持编写动态sql

2.MyBatis使用流程

环境搭建

  • 新建数据库

  • 新建项目

    • 新建一个普通maven项目

    • 删除src文件

    • 导入相关依赖:mysql驱动,mybatis,junit等

      1
      2
      3
      4
      5
      <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>x.x.x</version>
      </dependency>

创建一个模块

  • 编写mybatis核心配置文件,该配置文件包含对MyBatis系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务范围和控制方式的事务管理器(TransactionManager)
  • mybatis配置文件示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?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"/>
    <!--数据库连接的配置信息 驱动 URL 用户名 密码 -->
    <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>

    <!-- 将写好的sql映射文件组成到该处(见代码编写部分) -->
    <mappers>
    <mapper resource="BlogMapper.xml"/>
    </mappers>
    </configuration>
  • 构建 SqlSessionFactory对象

    • 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。
    • SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得
    • 而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例
    1
    2
    3
    String resource = "org/mybatis/example/mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • 获取 SqlSession实例、

    • 从 SqlSessionFactory 中可以获取 SqlSession实例

    • SqlSession 提供了在数据库执行 SQL 命令所需的所有方法

    • 我们可以通过SqlSession实例来直接执行已映射的 SQL 语句

      1
      2
      3
      4
      try (SqlSession session = sqlSessionFactory.openSession()) {
      BlogMapper mapper = session.getMapper(BlogMapper.class);
      Blog blog = mapper.selectBlog(101);
      }

代码编写

  • 实体类

    程序中的实体类对应着数据库中的字段

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class test {

    private Integer id;
    private String ame;

    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public String getName() {
    return Name;
    }
    public void setName(String lastName) {
    this.Name = Name;
    }
    }
  • Dao接口

    Dao接口用于操作数据库对象

    1
    2
    3
    public interface Dao{
    List<test> getList();
    }
  • 编写sql映射文件

    • 实现类由原来的Daolmpl(Dao接口实现类)转变为一个Mapper配置文件

    • namespace:名称空间 ,绑定一个对应的Dao或Mapper接口

    • id:sql的唯一标识

    • resultType:返回值类型

    • #{id}:从传递过来的参数中取出id值

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <?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="org.mybatis.example.BlogMapper">
      <select id="selectBlog" resultType="Blog">
      select * from Blog where id = #{id}
      </select>
      </mapper>

每个mapper.xml文件都要在Mybatis核心配置文件中注册

执行代码

Test测试编写:

  • 获取SqlSession对象
  • 执行sql(getMapper)
  • 关闭SqlSession

可能出现的问题:

  • sql映射配置文件没注册
  • 绑定接口错误
  • 方法名不对
  • 返回类型不对
  • Maven导出资源问题

3.CRUD

在sql映射文件中编写CRUD

实现步骤

  • 编写接口(Dao/Mapper)
  • 编写对应接口的sql语句
  • 测试

namespace

namespace中的包名要与Dao/mapper接口的包名一致

select

  • id:对应namespace接口文件中的方法名
  • resultType:sql语句执行的返回值
  • parameterType:参数类型

insert update delete

增删改标签在映射文件中编写sql语句,调用时都需要提交事物

错误分析

  • sql映射文件的标签和sql语句要对应
  • resource绑定mapper需要使用路径
  • 程序配置文件必须符合规范
  • NullPointerException,没有注册到资源

Map参数类型

  • 假设实体类或者数据库中的字段过多,我们可以使用Map作为parameterType的值
  • Map可以自动填充null
  • Map传递参数,直接在sql中取出key(多个参数用Map,或者注解)
  • 对象传递参数,在sql中取对象的属性(只有一个基本类型参数下使用)

模糊查询

  • Java代码执行时,传递通配符
  • 也可以在在sql拼接中使用通配符

4.配置解析

核心配置文件

  • mybatis-config.xml

  • MyBaits的配置文件包含了会深深影响MyBatis行为的设置和属性信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    properties(属性)
    settings(设置)
    typeAliases(类型别名)
    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)
    environments(环境配置)
    environment(环境变量)
    transactionManager(事务管理器)
    dataSource(数据源)
    databaseIdProvider(数据库厂商标识)
    mappers(映射器)

环境配置(environments)

  • 尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境
  • MyBatis默认事务管理器时JDBC,连接池POOLED

属性(properties)

  • 我们可以通过properties属性来实现引用外部配置文件,可以在其中增加一些属性配置(如果有同一字段,优先录取外部配置文件的)
  • 这些属性都是可外部配置且动态替换的,既可以在典型的Java属性文件中配置,也可以通过properties的子元素传递
  • 外部配置文件写入数据库连接相关属性

类型别名(ypeAliases)

  • 类型别名可为 Java 类型设置一个缩写名字
  • 它仅用于 XML 配置,意在降低冗余的全限定类名书写
  • 也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,默认使用 Bean 的首字母小写的非限定类名来作为它的别名

设置

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为

一个配置完整的 settings 元素的示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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>

映射器

MapperRegistry:注册绑定我们的Mapper文件

1
2
3
4
5
6
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

生命周期与作用域

作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题

SqlSessionFactoryBuilder:

  • 一旦创建了SqlSessionFactory,就不需要它了
  • 局部变量

SqlSessionFactory:

  • 数据库连接池
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
  • SqlSessionFactory最佳作用域是应用作用域
  • 最简单的就是使用单例模式或者静态单例模式 (保证全局只有一个SqlSessionFactory)

SqlSession:

  • 连接到连接池的一个请求
  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
  • 用完之后需要赶紧关闭

5.ResultMap结果集映射

当实体类中属性名和数据库中字段名不一致时会找不到对应字段

解决方案:

  • 在sql映射中为字段起别名,达到与实体类中属性名一致的目的
  • 通过resultMap结果集映射,让数据库中的字段映射到实体类的属性

6.日志

日志工厂

如果一个数据库操作出现了异常,我们需要排错,这时候往往要用到日志。MyBatis可以开启日志工厂,具体使用哪个日志实现,在设置中设定

Log4j

  • log4j简介

    • Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件……
    • 可以控制每一条日志的输出格式
    • 通过一个配置文件进行灵活配置,而不需要修改应用代码
  • log4j使用

    • 导入log4j依赖
  • 写log4j.properties配置文件

    • 使用log4j类格式化输出

7.分页

分页可以减少数据处理量

使用Limit分页

使用Mybatis实现分页

  • 接口
  • Mapper.xml(sql映射配置文件)
  • 测试

RowBounds分页

不建议在开发中使用

  • 接口
  • mapper.xml
  • 测试

分页插件

8.使用注解开发

面向接口编程

面向接口编程:解耦,可拓展,提高复用,分层开发中,上层不用管具体实现

关于接口的理解:

  • 接口时定义域实现的分离
  • 接口可以反映系统设计人员对系统的抽象理解

三个面向区别:

  • 面向对象:考虑问题时,以对象为单位,考虑它属性及方法
  • 面向过程:考虑问题时,以一个事务流程为单位,考虑它的实现
  • 面向接口:体现对系统整体的架构

注解开发

本质:反射机制实现

底层:动态代理

  • 注解在接口实现,取代了sql映射配置文件的功能
  • 需要在核心配置我文件中绑定接口
  • 测试

CRUD

  • 多个参数时,所有的参数前面必须加上@Param(“id”)的注解

  • 工具类创建时实现自动提交事务

  • 关于@Param()注解

    • 基本数据类型或String类型的参数需要加上

    • 引用类型不需要加

  • #{}相较于${}可以更有效防止注解

9.Lombok

Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法

10.多对一处理

找到一名学生对应的老师(有多个学生是同一个老师)

按照查询嵌套处理

类似于sql的子查询

  • 查询所有学生信息
  • 根据学生的tid寻找对应老师

按照结果嵌套处理

11.一对多处理

找到一名老师对应的多个学生

按照结果嵌套查询

按照查询嵌套查询

12.动态SQL

动态sql就是根据不同条件生成不同的sql语句

所谓动态sql,本质上还是sql语句,只是我们可以在sql层面,去执行一个逻辑代码

动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL格式排列组合即可

if

根据条件拼接出不同的sql语句

choose (when, otherwise )

类似于switch语句,匹配符合条件的标签拼接成新的sql语句

trim (where, set)

  • where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除
  • set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)

foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)

13.缓存

缓存简介

  • 存在内存中的临时数据
  • 将用户经常查询的数据放在缓存中,用户去查询数据可以直接在缓存中查询,提高了查询效率,解决了高并发系统的性能问题
  • 使用缓存可以减少与数据库交互次数,减少系统开销,提高系统效率
  • 经常查询而且不经常改变的数据使用缓存

Mybaiis缓存

  • MyBatis包含一个非常强大的查询缓存特性,非常方便定制和配置缓存,极大提高查询效率
  • MyBatis系统中默认定义两级缓存
    • 默认情况下,MyBatis开启了一级缓存(SqlSession本地缓存)
    • 二级缓存需要手动开启和配置(基于namespace级别的缓存,我们可以通过Cache接口自定义二级缓存)

一级缓存

  • 与数据库同异常会话期间查询到的数据会放到本地缓存中
  • 以后需要获取相同数据就可以直接在缓存中拿,而不必查询数据库

缓存失效的情况:

  • 查询不同的东西
  • 增删改操作会导致刷新缓存
  • 手动清理缓存

二级缓存

二级缓存又叫全局缓存,一个命名空间对应一个二级缓存

二级缓存工作机制:

  • 一个会话查询的数据会被放在当前会话的一级缓存中
  • 如果会话关闭,这个会话对应的一级缓存就被清除了
  • 但是如果开启了二级缓存,会话关闭后,缓存的数据可以被保存在二级缓存中
  • 新的会话查询就可以从二级缓存中获取内容