MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL

目录

MyBatis文档

《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

MyBatis源码及资料: https://github.com/coderZYGui/MyBatis-Study

MyBatis系列

  1. MyBatis — ORM思想、MyBatis概述、日志框架、OGNL
  2. MyBaits — MyBatis的CRUD操作、别名配置、属性配置、查询结果映射、Mapper组件、参数处理、注解开发
  3. MyBatis — 动态SQL、if、where、set、foreach、sql片段
  4. MyBatis — 对象关系映射、延迟加载、关联对象的配置选择
  5. MyBatis — 缓存机制、EhCache第三方缓存
  6. MyBatis — MyBatis Generator插件使用(配置详解)

一、 走进MyBatis

1.1、什么是框架?

跳转到目录

  • 什么是框架,框架从何而来,为什么使用框架?
  • 框架( framework) :
    • 是一系列jar包,其本质是对JDK功能的拓展。(类似SKD)
    • 框架 是一组程序的集合,包含了一系列的最佳实践,作用是解决某一个领域的问题。

1.2、 框架的形成

跳转到目录
最佳实践( Best Practice) :

  • 实际上是无数程序员经历过无数次尝试之后,总结出来的处理特定问题的特定方法。
  • 如果把程序员的自由发挥看作是一条通往成功的途径 ,最佳实践就是其中的最短路径,能极大的解放生产力

《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

1.3、 ORM思想

跳转到目录

  • 对象关系映射(Object Relational Mapping, 简称ORM): 是一种为了解决面向对象与关系数据库存在的互不匹配的问题的技术.
  • 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据, 将Java程序中的对象自动持久化到关系数据库中.
  • ORM 主要解决 对象-关系的映射
面向对象概念面向关系概念
对象表的行(记录)
属性表的列(字段)

《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

1.4、 常见的ORM框架

跳转到目录
把对象, 数据库的操作封装成一套API,具有操作数据库的增删改查等操作,而且具有独立性,当持久层技术层发生改变时,不用修改任何业务层代码.

  • JPA : 本身是一种ORM规范,不是ORM框架. 由各大ORM框架提供实现.(类似日志门面Slf4j)
    • Hibernate : 以前最流行的ORM框架.
    • MyBatis : 是目前最受欢迎的持久层ORM框架.

二、 MyBatis概述

跳转到目录

  • MyBatis 是一款优秀的持久层框架
  • 它支持定制化 SQL存储过程以及高级映射
  • MyBatis 避免了几乎所有的 JDBC 代码和 手动设置参数以及获取结果集
  • MyBatis 可以使用简单的 XML注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

2.1、 MyBatis架构图

跳转到目录
《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

2.2、 MyBatis核心组件

跳转到目录

  • SqISessionFactoryBuilder (构建器) : 根据配置信息或Java代码来构建 SqlSessionFactory对象。作用:创建SqlSessionFactory对象。
  • SqlSessionFactory (会话工厂) :好比是DataSource(创建连接的数据源) ,线程安全的,在应用运行期间不要重复创建多次,建议使用单例模式作用: 创建SqlSession对象
  • SqlSession (会话) :好比是Connection ,线程不安全的,每次使用开启新的SqlSession对象,使用完毕正常关闭,默认使用DefaultSqlSession。提供操作数据库的增删改查方法,可以调用操作方法,也可以操作Mapper组件。
  • Executor (执行器) : SqlSession本身不能直接操作数据库,需要Executor来完成,该接口有两个实现: 缓存执行器(缺省)、基本执行器。
  • MappedStatement :映射语句(MappedStatement)封装 执行语句时的信息: 如SQL、输入参数、输出结果

原理图:
《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》
更具体的底层原理图:
《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》
涉及的对象:

  • SqlSession :表示和数据库交互的会话,完成必要 数据库增删改查功能
  • Executor :执行器,是MyBatis调度的核心, 负责SQL语句的生成和查询缓存的维护。 (生成之后,会执行pluginAll方法)
  • StatementHandler :语句处理器,封装了JDBC的DML、DQL 操作、参数设置。(在创建对象时,会执行pluginAll方法)
  • ParameterHandler :参数处理器,把用户传入参数转换为JDBC需要的参数值。(在创建对象时,会执行pluginAll方法)
  • ResultSetHandler :结果集处理器,把结果集中的数据封装到List集合。(在创建对象时,会执行pluginAll方法)
  • TypeHandler :类型转换器, Java类型和JDBC类型的相互转换
  • MappedStatement :映射语句对象,维护了一条< insert|update|delete|select>节点的封装
  • SqlSource : SQL源, 根据用户传入的参数生成SQL语句,并封装到BoundSql中
  • BoundSql : SQL绑定, 封装SQL语句和对应的参数信息
  • Configuration : MyBatis 全局配置对象,封装所有配置信息

《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》
《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

三、 MyBatis入门

跳转到目录

3.1、 如何获得MyBatis?

跳转到目录

  • 通过Maven仓库
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>

3.2、 配置文件

跳转到目录
MyBatis 自身的配置文件有两种:

  • MyBatis全局配置文件/主配置文件.
    • 起名: 一般规定 mybatis-config.xml
    • 路径: 放在 resources 资源路径下
    • 参照: mybatis文档的 —- 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>
    <!--1.配置数据库的环境-->
    <environments default="development">
        <!--开发环境:在以后事务管理器和连接池都是交给Spring框架来管理-->
        <environment id="development">
            <!--事务管理器-->
            <transactionManager type="JDBC"/>
            <!--连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="1111"/>
            </dataSource>
        </environment>
    </environments>
    <!--2.关联映射文件-->
    <!-- 注意这里的路径是mybatis-config.xml文件找到UserMapper.xml的路径 如果在java的目录下,找不到UserMapper.xml -->
    <mappers>
        <mapper resource="com/sunny/dao/UserMapper.xml"/>
    </mappers>
</configuration>
  • MyBatis映射文件/Mapper文件
    • 起名: 一般见名知意 XxxMapper.xml, Xxx表示实体对象
    • 路径: Mapper文件和Mapper接口的路径要保持一致(包路径).
    • 参照: mybatis文档的 — XML映射文件章节
    • 内容:
      • 编写增删改查的SQL, 把SQL存放到insert | update | delete | select标签中去
      • 结果集映射: 解决表中的 列和对象中属性不匹配的问题.
      • 缓存配置

《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

<?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:绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.sunny.dao.UserDao">
    <!-- select元素: 专门用来做查询的SQL -id属性: 唯一标识,用来标识某一条SQL语句; 写Mapper接口中对应的接口名称 -parameterType属性: 表示执行该SQL语句需要的参数的类型(建议不写),MyBatis可以自行推断出来 -resultType属性: 把结果集中每一行数据封装成什么类型的对象 -->
    <select id="getUserList" resultType="com.sunny.domain.User">
        SELECT * FROM user;
    </select>
    <!-- #{id} 相当于在测试方法中selectOne传递过来的值 -->
    <select id="getUser" resultType="com.sunny.domain.User">
        SELECT * FROM user WHERE id = #{id}; <!-- #{id}相当于调用id的get方法 -->
    </select>
</mapper>

3.3、 查询操作

跳转到目录

  • UserDaoTest
public class UserDaoTest { 
    /** * 查询所有用户 * @throws IOException */
    @Test
    public void queryUserListTest() throws IOException { 

        //1. 获得sqlSession对象
        // SqlSession sqlSession = MybatisUtils.getSqlSession();

        //1. 从classpath路径去加载MyBatis全局配置文件:mybatis-config.xml
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        //2. 创建sqlSessionFactory对象,好比是DataSource
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3. 创建sqlSession对象,好比是Connection
        SqlSession sqlSession = factory.openSession();
        //4. 具体操作
        // 执行SQL(方式一): 底层使用反射+动态代理,创建出UserDao接口的实现类
         UserDao userDao = sqlSession.getMapper(UserDao.class);
         List<User> userList = userDao.getUserList();

        // 方式二
        // List<User> userList = sqlSession.selectList("com.sunny.dao.UserDao.getUserList");

        for (User user : userList) { 
            System.out.println(user);
        }

        // 关闭sqlSession
        sqlSession.close();
    }

    /** * 查询id为1的用户 * @throws IOException */
    @Test
    public void queryOneUserTest() throws IOException { 
        // 加载全局配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        // 构建sqlSessionFactory工厂类对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        // 根据sqlSession类对象来创建SqlSession对象
        SqlSession sqlSession = factory.openSession();
        // sqlSession相当于Connection,来执行SQL语句
        User user = sqlSession.selectOne("com.sunny.dao.UserDao.getUser", 1L);
        System.out.println(user);
    }
}
  • 抽取的MybatisUtils
// sqlSessionFactory 生产 sqlSession
public class MybatisUtils { 

    private static  SqlSessionFactory sqlSessionFactory;

    static { 
        try { 
            // 使用Mybatis的第一步: 获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) { 
            e.printStackTrace();
        }
    }

    // 既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
    // SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
    public static SqlSession getSqlSession(){ 
        return sqlSessionFactory.openSession();
    }
}

四、 日志框架

跳转到目录

参考mybatis文档: 日志

4.1、 为什么要用日志?

跳转到目录

  • 比起System.out.println, 日志框架可以把日志的输出代码分离;
  • 日志框架可以方便定义日志的输出环境,如 控制台,文件,数据库;
  • 日志框架可以方便的定义日志的输出格式和输出级别;

《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

4.2、 常见的日志框架

跳转到目录

  • JUL : JDK1.4版本以后开始提供的一个自带的日志库实现,太简单, 不支持占位符显示,拓展性差,使用很少。
  • Log4j : Apache下功能非常丰富的日志库实现,功能强大,可以把日志输出到控制台、文件中,是出现比较早且最受欢迎日志组件。并且Log4j可以允许自定义日志格式和日志等级,帮助开发人员全方位的掌控日志信息。
  • Log4j2 :是Log4j的升级,基本上把Log4j版本的核心全部重构,而且基于Log4j做了很多优化和升级。SLF4J :好比是Commons-logging是日志门面,本身并无日志的实现,制定了日志的规范,使用时得拷贝整合包。
  • Logback : 由Log4j创始人设计的另-个开源日志组件,也是作为Log4j的替代者出现的。
  • 补充: Commons-logging : Apache提供的日志规范,即日志门面。需要用户可以选择第三方的日志组件作为具体实现,本身会通过动态查找的机制找出真正日志的实现库。

  • 最牛的日志门面: Slf4j

  • Logback速度和效率都比Log4j高,而且官方是建议和SLF4j门面一起使用 ,Logback. sIf4j、 Log4j 都是出自同一个人,所以默认对SLF4J无缝结合。

  • 现在市面以及公司采用的日志技术 : Slf4j门面 + Log4j2日志实现

4.3、 日志级别

跳转到目录

  • ERROR > WARN> INFO > DEBUG > TRACE
  • 如果设置级别为INFO ,则优先级高于等于INFO级别(如: INFO、WARN、ERROR )的日志信息将可以被输出,小于该级别的如DEBUG和TRACE将不会被输出。
  • 总结:日志级别越低,输出的日志越详细.

4.4、 日志文件的组成

跳转到目录

  • Log4j主要由 Loggers (日志记录器)Appenders(输出控制器)Layout(日志格式化器) 组成。
    • Loggers 控制日志的输出以及输出级别(JUL做日志级别用Level类);
    • Appenders 指定日志的输出方式(输出到控制台、文件等);
    • Layout 控制日志信息的输出格式。

《MyBatis——ORM思想、MyBatis概述、MyBaits核心组件、日志框架、OGNL》

4.5、 日志的使用

跳转到目录

  • 首先添加Log4j的坐标
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
  • 在Mybatis的全局配置文件中设置
 <!--日志技术-->
 <settings>
     <setting name="logImpl" value="LOG4J"/>
 </settings>
  • 定义日志文件
# Global logging configuration
#设置全局rootLogger的日志配置:输出Error级别,输出到控制台
log4j.rootLogger=ERROR, stdout

# MyBatis logging configuration...
#设置自定义Logger的日志级别(测试类的包名com.sunny.dao)
log4j.logger.com.sunny.dao=DEBUG

# 输出到控制台,并设置输出日志格式...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
  • 自定义日志
    // 自定义日志
    private static Logger logger = Logger.getLogger(UserDaoTest.class);

    @Test
    public void testLogger() throws Exception{ 
        // 如果日志输出级别为INFO,则输出
        if (logger.isInfoEnabled()){ 
            logger.info("银行转账操作");
        }
        if (logger.isDebugEnabled()){ 
            logger.debug("查询数据库");
        }
        if (logger.isTraceEnabled()){ 
            logger.trace("连接数据库");
        }
        if (logger.isTraceEnabled()){ 
            logger.trace("执行SQL");
        }
        if (logger.isDebugEnabled()){ 
            logger.debug("转账");
        }
        if (logger.isInfoEnabled()){ 
            logger.info("银行转账成功");
        }
    }

五、 作用域和生命周期

跳转到目录

  • SqISessionFactoryBuilder(作用: 加载mybatis-config.xml全局配置文件, 创建SqlSessionFactory对象)
    • 这个类可以被实例化、使用和丢弃,一旦创建了SqlSessionFactory ,就不再需要它了所以SqISessionFactoryBuilder的对象要放在方法作用域(局部作用域)中
    • 你可以重用SqlSessionFactoryBuilder 来创建多个SqlSessionFactory 实例,但是最好还是不要让其一直存在, 以保证所有的XML解析资源开放给更重要的事情.
  • SqISessionFactory
    • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在 (单例),没有任何理由对它进行清除或重建。
    • 使用SqISessionFactory 的最佳实践是在应用运行期间不要重复创建多次, 多次重建SqlSessionFactory被视为一种代码”坏味道( bad smell)”.因此SqISessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
  • SqlSession
    • 每个线程都应该有它自己的SqlSession 实例。SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
    • 绝对不能将SqlSession 实例的引用放在一个类的静态域, 变为对象的临界资源, 甚至一个类的实例变量也不行。也绝不能将SqlSession 实例的引用放在任何类型的管理作用域中。否则会造成线程安全问题
    原文作者:white camel
    原文地址: https://blog.csdn.net/m0_37989980/article/details/104423309
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞