MyBatis基础总结

MyBatis基础总结

1、JDBC

JDBC(Java Data Base Connectivity)用于执行SQL语句的Java API,可以为多种关系的数据库提供统一访问,有Java语言编写的类和接口组成,是Java访问数据库的标准规范。

获取jar包官网:https://downloads.mysql.com/archives/c-j/

JDBC开发步骤

// 1.注册JDCB驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.建立并获取数据库连接
Connection conn = DriverManager.getConnection(url,user,password)
// 3.创建JDBC Statement对象
Statement sta = conn.createStatement();
// 4.执行SQL语句,返回结果
// 		执行增删改executeUpdate(String sql);返回值int
/*		查:executeQuery(String sql); 返回值ResultSet,使用next遍历,用		getXXX("字段名")获取字段信息。
*/
String sql = "";
<E> result = sta.executeUpdate(sql);
// 5.释放资源

预处理对象PreparedStatement

执行流程:

  • 加载JDBC驱动
  • 建立并获取数据库连接
  • 创建JDBC Statement(PreparedStatement)对象
  • 设置SQL语句的传入参数
  • 执行SQL语句并获得查询结果
  • 对查询结果进行转换处理并将处理结果返回
  • 释放相关资源
String sql = "insert into sort(sid,sname) values(?,?)";
PreparedStatement psmt = conn.prepareStatement(sql);
psmt.setInt(1,6);
psmt.setString(2,"大五");
  • 解决SQL语句的拼串传值问题

JDBC工具类

public class JDBCUtils {
    public static Connection getConnection(){
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=UTF-8";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url,user,password);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    public static void close(Connection conn, Statement sta){
        if (conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(sta != null){
            try {
                sta.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

Druid连接池

执行流程:

2、MyBatis

2.1 MyBatis框架介绍

  • MyBatis是一个优秀的持久层框架,内部封装了JDBC
  • MyBatis通过xml或注解的方式配置
  • 采用ORM思想解决实体类和数据库映射问题,对JDBC进行封装,屏蔽了JDBC API底层访问细节。(让实体类和数据库表进行一一对应关系,不需要直接操作数据库表,直接操作表对应的实体类对象)
    • O(Object):面向对象领域的JavaBean对象
    • R(Relational):关系型数据库领域的表的结构
    • M(Mapping):映射
  • MyBatis执行流程(重要):加载配置->SQL解析->SQL执行->结果映射->释放连接
    • 加载配置并初始化:从配置文件、或java代码注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
    • 接收调用请求:调用Mybatis提高的API,传入SQL的ID和参数对象,将请求传递给下层的请求处理层进行处理。
    • 处理操作请求
      • 根据SQL的id查找对应的MappedStatement对象
      • 根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数
      • 获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果
      • 根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果
      • 释放连接资源
    • 返回处理结果:将最终的处理结果返回

2.2 MyBatis、xml方式配置

新建maven工程→导入mybatis坐标→编写mybatis配置文件→编写映射文件

导入mybatis坐标

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
</dependency>

编写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"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="cn/xuzy/dao/userMapper.xml"/>
    </mappers>
</configuration>

MyBatis配置文件标签

  • properties

    • property:配置数据库连接(driver、url、username、password)
  • settings

    • setting:配置全局参数:配置延迟加载
    <settings> 
        <!-- 设置懒加载 -->
    	<setting name="lazyLoadingEnabled" value="true"/> 
    	<setting name="aggressiveLazyLoading" value="false"/> 
        
        <!-- 缓存 -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 设置日志记录 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings> 
    
  • typeAliases

    • typeAliase:单个实体类起别名
      • type:要起别名的全限定类名
      • alias:要起的别名
    • package:批量起别名,在包下默认使用类名首字母小写的非限定类名作为别名
  • environments

    • environment:环境集合数据对象,配置数据源和事务管理
      • dataSource:type属性指定使用的数据库连接池(POOLED/UNPOOLED/JNDI)
        • property:配置数据库连接
      • transactionManager:事务管理
  • mappers

    • mapper:映射SQL的xml配置文件(文件名要与dao的全限定名相同)
      • resource:使用相对于类路径的mapper资源引用(引用xml资源)
      • class:使用映射器接口实现类的完全限定类名,需要配置文件名和接口名称一致,并在位于同一目录下(映射包下接口名)
    • package
      • name:将包内的映射器接口全部注册为映射器(映射整个包所有接口)

编写SQL映射配置文件

<?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="cn.xuzy.dao.UserMapper">
    <select id="selectUser" resultType="cn.xuzy.pojo.User">
        select * from mybatis
    </select>
    
    <select id="selectUserById" resultType="cn.xuzy.pojo.User">
        select * from user where id = #{id}
    </select>
</mapper>
  1. SQL语句配置标签:

    // id属性必须和持久层(dao)接口的方法名相同,resultType可以直接引用实体类的全限定类名
    <select>,<insert>,<delect>,<update>其标签的属性为
    	- resultType:指定结果集的类型(自定义对象需要写全限定类名)
    	- parameterType:用于指定传入参数的类型(基本类型可以直接写类型的名称,自定义实体类需要写全限定类名)
    
    • mapper:namespace属性:必须跟某个(dao)接口同名
      • id:对应接口里的方法名,SQL语句实现其功能
      • parameterType:用于指定传入参数的类型(基本类型可以直接写类型的名称,自定义实体类需要写全限定类名)
      • resultType:结果集封装
  2. SQL语句中使用#{}和${}

    • #{}:表示一个占位符,通过#{}可以实现preparedStatement向占位符中设置值。#{}可以有效防止SQL注入。#{}可以接收基本类型值或pojo(自定义对象)属性值。语法#{对象.属性值}
    • ** : 直 接 进 行 字 符 串 替 换 ∗ ∗ , 可 以 将 p a r a m e t e r T y p e 传 入 的 内 容 拼 接 在 S Q L 中 且 不 进 行 J D B C 类 型 转 换 。 {}:直接进行字符串替换**,可以将parameterType传入的内容拼接在SQL中且不进行JDBC类型转换。 parameterTypeSQLJDBC{}可以接收基本类型值或pojo属性值
  3. resultMap结果类型封装

    resultMap标签可以建立查询的列名和实体类属性名称不一致时建立对应关系,从而实现封装。

    标签属性:

    • type:指定实体类的全限定类名。
    • id:给定一个唯一标识,给select标签引用使用的。

    子标签:

    • id:指定主键字段,标签属性:
      • column:指定数据库表列名
      • property:指定实体类属性名称
    • result:指定非主键字段
      • 同id标签属性。
  4. 动态SQL语句

    动态SQL指的是根据不同的查询条件,生成不同的SQL语句

    • if
    • choose(when, otherwise)
    • trim(where, set)
    • foreach
      • collection:指定输入对象中的集合属性
      • item:每次遍历生成的对象
      • open:开始遍历时的拼接字符串
      • close:结束时拼接的字符串
      • separator:遍历对象之间需要拼接的字符串

    动态SQL本质是SQL语句的拼接问题。

编写mabatis工具类

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连接
   public static SqlSession getSession(){
       return sqlSessionFactory.openSession();
  }
}
  1. 生命周期、作用域
  • SqlSessionFactoryBuilder:最佳作用域是方法作用域,也就是局部方法变量
  • SqlSessionFactory:声明周期在整个MyBatis应用中,最佳作用域是应用作用域。单例,因此用static代码块,在整个应用只执行一次new操作。

2.3 MaBatis 基于注解配置

  • @Select()
  • @Update()
  • @Insert()
  • @Delect()
    • @Param:用于给方法参数起一个名字,与#{}括号里的名称一致
      • 在方法只接受一个参数情况下,可以不使用@Param
      • 在多个接受多个参数的情况下,建议使用@Param给参数命名
      • 如果参数是JavaBean,则不能使用@Param
@Select("select * from user")
public List<User> getAllUser();

//根据id删除用
@Delete("delete from user where id = #{id}")
int deleteUser(@Param("id")int id);
<!-- mybatis核心配置文件注入-->
<mappers>
	<mapper class = "cn.xuzy.dao.UserDao"/>
</mappers>
  • @Result():实现结果集封装
    • id:主键字段
    • column:非主键字段
    • property:JavaBean要装配属性名
    • one:需要使用@one注解
      • select:
    • many:需要使用@many注解

3、缓存

  • 存在于内存中的临时数据
  • 将用户经常查询的数据放在缓存中,用户去查询数据就不用从磁盘上查询,从缓存中查询,从而提高查询效率。

使用缓存好处

  • 减少和数据库的交互次数,减少系统开销,提高系统效率

什么场景下不使用缓存

  • 经常查询并且不经常改变的数据

4.1 Mybatis缓存

MyBatis系统默认定义了两级缓存:一级缓存和二级缓存

  • 默认情况下,只有一级缓存开启
  • 二级缓存需要手动开启配置,基于namespace级别的缓存
  • 为了提高扩展性,MyBatis定义了缓存接口Cache。通过实现Cache接口来自定义二级缓存

一级缓存(本地缓存)

  • 与数据库的同一次会话期间查询到的数据会放到本地缓存中
  • 以后如果需要获取相同的数据,直接从缓存中获取,不需要去查询数据库

二级缓存

  • 二级缓存也叫全局缓存
  • 基于namespace级别的缓存,一个名称空间对应一个二级缓存
  • 工作机制
    • 一个会话查询一条数据,这个数据会放到当前会话的一级缓存,如果会话关闭,这个会话对应的一级缓存数据会被保存到二级缓存,新的会话就可以从二级缓存中获取数据
<setting name="cacheEnabled" value="true"/>

4、MyBatis执行流程

4.1 底层运行逻辑

MyBatis核心类

  • SqLSessionFactoryBuilder:用于创建一个SqlSessionFactory
  • SqlSessionFactory:
    • 每一个MyBatis应用都是以一个SqlSessionFactory的实例为中心。
    • 他可以有SqlSessionFactoryBuilder从xml配置中构建SqlSessionFactory实例。
    • SqlSessionFactory的最佳作用域是应用作用域,建议使用单例模式或静态单例模式。
    • 多个数据看应配置多个SqlSessionFactory与之一一对应。
  • SqlSession:
    • SqlSession是一个接口,优良实现类,默认使用DefaultSqlSession, SqlSessionManager
    • SqlSession通过内部的执行器(Executor)来对数据进行CRUD
    • 线程不安全,每次操作完数据库后斗鱼调用close对其进行关闭。通过try-finally
  • Executor:
  • MappedStatement:
    • 存放SQL映射文件中的信息,包括sql语句、输入参数、输出参数等,一个MappedStatememt对象。

MyBatis功能框架

img

MyBatis功能架构分为三层:

  • **API接口层:**提供给外部使用的接口API,通过这些API操作数据库。接口层接收到调用请求就会调用数据处理层来完成具体是数据处理
  • **数据处理层:**负责CRUD和执行结果映射
  • **基础支撑层:**负责最基础功能支撑,包括连接管理、事务管理、配置加载和缓存处理

4.2 详细执行流程

img

参考文献

  1. 【狂神说Java】Mybatis最新完整教程IDEA版通俗易懂:https://www.bilibili.com/video/BV1NE411Q7Nx?from=search&seid=3950126876256805284
  2. Mybatis工作流程及其原理与解析:https://blog.csdn.net/u010890358/article/details/80665753
  3. Mybatis实现原理深入解析:https://blog.csdn.net/xudan1010/article/details/53435018
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值