目录
- 一、走进MyBatis
- 1.1、什么是框架?
- 1.2、 框架的形成
- 1.3、 ORM思想
- 1.4、 常见的ORM框架
- 二、 MyBatis概述
- 2.1、MyBatis架构图
- 2.2、MyBatis核心组件
- 三、MyBatis入门
- 3.1、如何获得MyBatis?
- 3.2、配置文件
- 3.3、查询代码
- 四、日志框架
- 4.1、为什么要用日志?
- 4.2、常见的日志框架
- 4.3、日志级别
- 4.4、日志文件的组成
- 4.5、日志的使用
- 五、OGNL
- 六、作用域和生命周期
MyBatis源码及资料: https://github.com/coderZYGui/MyBatis-Study
MyBatis系列
- MyBatis — ORM思想、MyBatis概述、日志框架、OGNL
- MyBaits — MyBatis的CRUD操作、别名配置、属性配置、查询结果映射、Mapper组件、参数处理、注解开发
- MyBatis — 动态SQL、if、where、set、foreach、sql片段
- MyBatis — 对象关系映射、延迟加载、关联对象的配置选择
- MyBatis — 缓存机制、EhCache第三方缓存
- MyBatis — MyBatis Generator插件使用(配置详解)
跳转到目录
- 什么是框架,框架从何而来,为什么使用框架?
- 框架( framework) :
- 是一系列
jar
包,其本质是对JDK功能的拓展。(类似SKD) - 框架 是一组程序的集合,包含了一系列的最佳实践,作用是解决某一个领域的问题。
- 是一系列
跳转到目录 最佳实践( Best Practice) :
- 实际上是无数程序员经历过无数次尝试之后,总结出来的处理特定问题的特定方法。
- 如果把程序员的自由发挥看作是一条通往成功的途径 ,最佳实践就是其中的最短路径,能极大的解放生产力
跳转到目录
对象关系映射(Object Relational Mapping, 简称ORM)
: 是一种为了解决面向对象与关系数据库存在的互不匹配
的问题的技术.- 简单的说,
ORM是通过使用描述对象和数据库之间映射的元数据, 将Java程序中的对象自动持久化到关系数据库中
. - ORM 主要解决 对象-关系的映射
跳转到目录 把对象, 数据库的操作封装成一套API
,具有操作数据库的增删改查等操作,而且具有独立性,当持久层技术层发生改变时,不用修改任何业务层代码.
- JPA : 本身是一种
ORM规范
,不是ORM框架. 由各大ORM框架提供实现.(类似日志门面Slf4j)- Hibernate : 以前最流行的ORM框架.
MyBatis
: 是目前最受欢迎的持久层ORM框架.
跳转到目录
- MyBatis 是一款优秀的持久层框架
- 它支持
定制化 SQL
、存储过程
以及高级映射
。 - MyBatis 避免了几乎所有的
JDBC
代码和手动设置参数
以及获取结果集
。 - MyBatis 可以使用简单的
XML
或注解
来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
跳转到目录
跳转到目录
SqISessionFactoryBuilder (构建器)
: 根据配置信息或Java代码来构建 SqlSessionFactory对象。作用:创建SqlSessionFactory对象。SqlSessionFactory (会话工厂)
:好比是DataSource(创建连接的数据源) ,线程安全的,在应用运行期间不要重复创建多次,建议使用单例模式
。作用: 创建SqlSession对象SqlSession (会话)
:好比是Connection ,线程不安全的,每次使用开启新的SqlSession对象,使用完毕正常关闭,默认使用DefaultSqlSession。提供操作数据库的增删改查方法,可以调用操作方法,也可以操作Mapper
组件。Executor (执行器)
: SqlSession本身不能直接操作数据库,需要Executor
来完成,该接口有两个实现: 缓存执行器(缺省)、基本执行器。MappedStatement
:映射语句(MappedStatement)封装 执行语句时的信息: 如SQL、输入参数、输出结果
原理图: 更具体的底层原理图:
涉及的对象:
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 全局配置对象,封装所有配置信息
。
跳转到目录
3.1、 如何获得MyBatis?跳转到目录
- 通过Maven仓库
org.mybatis
mybatis
3.5.3
3.2、 配置文件
跳转到目录 MyBatis 自身的配置文件有两种:
- MyBatis全局配置文件/主配置文件.
- 起名: 一般规定
mybatis-config.xml
- 路径: 放在
resources
资源路径下 - 参照: mybatis文档的 ---- XML配置章节
- 内容:
- 全局的配置信息
- 属性配置信息
- 插件配置信息
- 配置环境信息(连接池+事务)
- 关联映射文件
- 起名: 一般规定
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
- MyBatis映射文件/Mapper文件
- 起名: 一般见名知意
XxxMapper.xml
, Xxx表示实体对象 - 路径: Mapper文件和Mapper接口的路径要保持一致(包路径).
- 参照: mybatis文档的 — XML映射文件章节
- 内容:
- 编写增删改查的SQL, 把SQL存放到
insert | update | delete | select
标签中去 - 结果集映射: 解决表中的 列和对象中属性不匹配的问题.
- 缓存配置
- 编写增删改查的SQL, 把SQL存放到
- 起名: 一般见名知意
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
SELECT * FROM user;
SELECT * FROM user WHERE id = #{id};
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 userList = userDao.getUserList();
// 方式二
// List 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
, 日志框架可以把日志的输出
和代码分离
; - 日志框架可以方便定义日志的输出环境,如 控制台,文件,数据库;
- 日志框架可以方便的定义日志的输出格式和输出级别;
跳转到目录
- 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日志实现
跳转到目录
ERROR > WARN> INFO > DEBUG > TRACE
- 如果设置级别为INFO ,则优先级高于等于INFO级别(如: INFO、WARN、ERROR )的日志信息将可以被输出,小于该级别的如DEBUG和TRACE将不会被输出。
- 总结:日志级别越低,输出的日志越详细.
跳转到目录
- Log4j主要由
Loggers
(日志记录器)、Appenders
(输出控制器) 和Layout
(日志格式化器) 组成。- Loggers 控制日志的输出以及输出级别(JUL做日志级别用Level类);
- Appenders 指定日志的输出方式(输出到控制台、文件等);
- Layout 控制日志信息的输出格式。
跳转到目录
- 首先添加Log4j的坐标
log4j
log4j
1.2.17
- 在Mybatis的全局配置文件中设置
- 定义日志文件
# 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解析资源开放给更重要的事情.
- 这个类可以被实例化、使用和丢弃,一旦创建了SqlSessionFactory ,就不再需要它了。
SqISessionFactory
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在 (单例),没有任何理由对它进行清除或重建。
- 使用SqISessionFactory 的最佳实践是在应用运行期间不要重复创建多次, 多次重建SqlSessionFactory被视为一种代码"坏味道( bad smell)”.因此SqISessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用
单例模式
或者静态单例模式。
SqlSession
每个线程都应该有它自己的SqlSession 实例。SqlSession的实例不是线程安全的,因此是不能被共享
的,所以它的最佳的作用域是请求或方法作用域
。- 绝对不能将SqlSession 实例的引用放在一个类的静态域, 变为对象的临界资源, 甚至一个类的实例变量也不行。也绝不能将SqlSession 实例的引用放在任何类型的管理作用域中。
否则会造成线程安全问题