第一章 mybatis基础
官网:https://mybatis.org/mybatis-3/zh/getting-started.html
第一节 orm思想
**对象关系映射**(Object Relational Mapping,简称ORM) ORM是通过使用描述对象和数据库之间映射的元数据,元数据一般采用XML格式,并且存放在专门的对象一映射文件中。将程序中的对象自动持久化到关系数据库中。
第二节 mybatis简介
mybatis官网:https://mybatis.org/mybatis-3/zh/index.html
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old/Ordinary Java Objects,普通老式 Java 对象)为数据库中的记录。
第三节 mybatis工作原理
SqlMapConfig.xml 主要是配置了数据库的连接信息,事务等还包括sql语句的映射文件(xxMapper.xml)
sqlSessionFactory:会话工厂,根据资源加载类获取数据库配置文件信息而生成。主要的作用就是生成SqlSession对象
SqlSession:由SqlsessionFactory生成,主要作用就是操作数据库(增删改查)
Excutor:分为基本执行器和缓存执行器,为sqlsession执行数据库的操作
MapperedStatement 底层封装对象,对数据库的配置信息进行封装(
sql语句,
输入参数,(包括java简单类型,HashMap类型,实体类型)
输出结果类型(包括java简单类型,HashMap类型,实体类型))
执行结构图
架构分为三层:
接口层:给应用程序提供一系列的数据接口。(CRUD) ;SqlSession数据处理层:
接口层传递参数,sql命令,在数据处理层进行处理,返回对应的结果映射。
基础支撑层:提供最基础的底层的操作:连接管理(连接池),事务管理(增、删、改),配置加载
(读取配置信息),缓存(一级缓存,二级缓存)。
第四节 入门示例
主配置
<?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">
<!--dtd = document type definition 规定了当前文档类型定义格式-->
<configuration>
<plugins>
<plugin interceptor="com.aaa.mybatis.plugin.PagePlugin">
<property name="aaa" value="1"></property>
</plugin>
</plugins>
<!--环境配置 可以配置多个环境-->
<environments default="development">
<!--具体环境配置-->
<environment id="development">
<!--事务管理配置 type ="jdbc" 自行处理事务 type="managed" 把事务交给容器管理-->
<transactionManager type="JDBC"/>
<!--数据源配置 UNPOOLED|POOLED|JNDI -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///test?serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--映射文件配置-->
<mappers>
<mapper resource="mappers/DeptMapper.xml"/>
<!--<mapper class="com.aaa.mybatis.dao.DeptDaoPlus"></mapper>-->
</mappers>
</configuration>
环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:
每个数据库对应一个 SqlSessionFactory 实例
为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
如果忽略了环境参数,那么将会加载默认环境,如下所示:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
https://mybatis.org/mybatis-3/zh/configuration.html#environments
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
- JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
- MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为
数据源(dataSource)
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
- 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。
有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:
- driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
- url – 这是数据库的 JDBC URL 地址。
- username – 登录数据库的用户名。
- password – 登录数据库的密码。
- defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
- defaultNetworkTimeout – 等待数据库操作完成的默认网络超时时间(单位:毫秒)。查看 java.sql.Connection#setNetworkTimeout() 的 API 文档以获取更多信息。
作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”前缀即可,例如: - driver.encoding=UTF8
这将通过 DriverManager.getConnection(url, driverProperties) 方法传递值为 UTF8 的 encoding 属性给数据库驱动。
POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
除了上述提到 UNPOOLED 下的属性外,还有更多属性用来配置 POOLED 的数据源:
- poolMaximumActiveConnections – 在任意时间可存在的活动(正在使用)连接数量,默认值:10
- poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
- poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
- poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000 毫秒(即 20 秒)。
- poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnections 与 poolMaximumLocalBadConnectionTolerance 之和。 默认值:3(新增于 3.4.5)
- poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动出错时返回恰当的错误消息。
poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。 - poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。
JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。这种数据源配置只需要两个属性: - initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么将会直接从 InitialContext 中寻找 data_source 属性。
- data_source – 这是引用数据源实例位置的上下文路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。
和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给 InitialContext。比如: - env.encoding=UTF8
这就会在 InitialContext 实例化时往它的构造方法传递值为 UTF8 的 encoding 属性。
1、什么是数据库连接池?
数据库连接池(Database Connection Pooling)在程序初始化时创建一定数量的数据库连接对象并将其保存在一块内存区中,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个;释放空闲时间超过最大空闲时间的数据库连接以避免因为没有释放数据库连接而引起的数据库连接遗漏。
即在程序初始化的时候创建一定数量的数据库连接,用完可以放回去,下一个在接着用,通过配置连接池的参数来控制连接池中的初始连接数、最小连接、最大连接、最大空闲时间这些参数保证访问数据库的数量在一定可控制的范围类,防止系统崩溃,使用户的体验好
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">
<!--1,隔离语句 2,绑定接口-->
<mapper namespace="com.aaa.mybatis.dao.DeptDao">
<!--部门列表查询-->
<select id="listDept" resultType="com.aaa.mybatis.entity.Dept">
<!--查询映射不区分大小写-->
select deptno,dname as deptName,loc from dept
</select>
</mapper>
工厂类
package com.aaa.mybatis.util;
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* fileName:SqlSessionFactoryUtil
* description: SqlSessionFactory工具类,提供工厂的创建方法及生产SqlSession方法
* author:zz
* createTime:2020/9/15 11:31
* version:1.0.0
*/
public class SqlSessionFactoryUtil {
//1 私有构造
private SqlSessionFactoryUtil(){};
//2 静态私有属性
private static SqlSessionFactory sqlSessionFactory;
// 静态单例模式
static{
InputStream inputStream = null;
try {
//mybatis提供Resources 中提供getResourceAsStream 根据资源得到流
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//mybatis提供SqlSessionFactoryBuilder 中提供build方法用来创建工厂
sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(inputStream);
//sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(inputStream!=null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//3 提供对外创建SqlSession方法
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
测试类
/**
* 测试列表方法
*/
@Test
public void testListDept(){
SqlSession sqlSession = null;
try {
// System.out.println("abc".indexOf("d"));
//使用工具类获取sqlSession
sqlSession = SqlSessionFactoryUtil.getSqlSession();
//使用jdk代理(代理接口)生成接口DeptDao代理对象
DeptDao deptDao = sqlSession.getMapper(DeptDao.class);//多态
//获取列表
List<Dept> deptList = deptDao.listDept();
//判断循环,输出
if(deptList!=null&&deptList.size()>0){
for (Dept dept : deptList) {
System.out.println("部门名称:"+dept.getDeptName()+",位置:"+dept.getLoc());
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(sqlSession!=null){
//官网建议放finally 关闭
sqlSession.close();
}
}
}
第五节 关键类作用域和生命周期
官网: https://mybatis.org/mybatis-3/zh/getting-started.html
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
SqlSessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:
try (SqlSession session = sqlSessionFactory.openSession()) {
// 你的应用逻辑代码
}
在所有代码中都遵循这种使用模式,可以保证所有数据库资源都能被正确地关闭。
第六节 部分配置讲解
<?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">
<!--dtd = document type definition 规定了当前文档类型定义格式-->
<configuration>
<settings>
<!--让控制台打印语句-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="jdbcTypeForNull" value="NULL"></setting>
<!--全局缓存配置 让所有二级缓存不生效,配置false -->
<!--<setting name="cacheEnabled" value="false"></setting>-->
</settings>
<!--别名配置-->
<typeAliases>
<!-- <typeAlias type="com.aaa.mybatis.entity.Dept" alias="dt"></typeAlias>-->
<package name="com.aaa.mybatis.entity"></package>
</typeAliases>
<!--全局设置配置-->
<!--环境配置 可以配置多个环境-->
<environments default="development">
<!--具体环境配置-->
<environment id="development">
<!--事务管理配置 type ="jdbc" 自行处理事务 type="managed" 把事务交给容器管理-->
<transactionManager type="JDBC"/>
<!--数据源配置 UNPOOLED|POOLED|JNDI -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///test?serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--映射文件配置-->
<mappers>
<mapper resource="mappers/DeptMapper.xml"/>
<mapper resource="mappers/EmpMapper.xml"/>
<mapper class="com.aaa.mybatis.dao.NewsDao"></mapper>
</mappers>
</configuration>
junit单元测试
@Before
在@Test之前执行的代码
@After
在@Test之后执行的代码
@Test
单元测试
单元测试的方法是没有返回值 void
mybatis的编程步骤:
1.读取配置文件
2. 创建 SqlSessionFactory
3 通过 SqlSessionFactory 创建 SqlSession
4 通过 sqlsession 执行数据库操作
5 调用 session.commit()提交事务
6. 调用 session.close()关闭会话
异常:
mapper文件没有注入到mybatis里面
插件:
上课例子:
125课堂代码:附件: mybatis-01.rar https://uploader.shimo.im/f/DGggffCCaNnpQE2R.rar?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDUxNzYwMzQsImciOiJQN3pGMGF4cGpvQU1PTTN3IiwiaWF0IjoxNjQ1MTc1NzM0LCJ1c2VySWQiOjczODQ2MzE3fQ.Fbxa3SwMjUZWzmOZII9ojzJ4SF07g4pmoBmxjxmy94o
130代码:附件: mybatis-01.rar https://uploader.shimo.im/f/cyNoBOTawJ0IoAxM.rar?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDUxNzYwMzQsImciOiJQN3pGMGF4cGpvQU1PTTN3IiwiaWF0IjoxNjQ1MTc1NzM0LCJ1c2VySWQiOjczODQ2MzE3fQ.Fbxa3SwMjUZWzmOZII9ojzJ4SF07g4pmoBmxjxmy94o