MyBatis

MyBatis

MyBatis是什么 ?
MyBatis 是一款优秀的持久层框架,支持定制化SQL,储存过程以及高级映射。
它为什么而存在,或者说它可以干什么
MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录

一、基础知识

ORM

ORM 对象关系映射,用于现实面向对象编程语言里不同类型系统的数据之间的转换。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射

  • 异构性:ORM可以解决数据库与程序间的异构性,比如在JAVA中我们使用String表示字符串,而Oracle中可使用varchar2,MySQL中可使用varchar,SQLServer可使用nvarchar。
  • 映射:ORM提供了实现持久化层的另一种模式,采用映射元数据(XML)来描述对象-关系的映射细节,使得ORM中间件能在任何一个Java应用的业务逻辑层和数据库之间充当桥梁,关系数据库的每一行映射为每一个对象。 关系数据库的每一列映射为对象的每个属性
  • 经典的ORM框架
    Hibernate:全自动的框架,强大,复杂笨重、学习成本高
    MyBatis:半自动的框架(懂数据库的人 才能操作)必须要自己写sql
    JPA:全称Java Persistence Api ,是java自带的框架

二、架构

在这里插入图片描述

  • 接口层:接口层主要定义的是与数据库进行交互的方式
  • 数据处理层:这是Mybatis的核心,负责参数映射和动态SQL生成,生成之后Mybatis执行SQL语句,并将返回的结构映射成自定义的类型
  • 框架支撑层:负责最基础的功能支撑,包括连接管理,事务管理,配置加载和缓存处理,这些都是公用的东西,将他们抽取出来作为最基础的组件。为上层数据处理层提供最基础的支撑

三、工作机制

  • 根据XML或者注解加载SQL语句、参数映射、结果映射到内存
  • 应用程序调用API传入参数和SQL ID
  • MyBatis 自动生成SQL语句完成数据库访问,转换执行结果返回应用程序。

工作流程

  1. Mybatis启动时,解析两种配置文件,作为Configuration配置对象。
    1. 全局配置文件:SqlMapConifg.xml,Mybatis运行的环境
    2. 映射器配置文件:Mapper.xml,包含了如何控制Mybatis的行为,对数据库所下达的相关的指令。
  2. 操作SqlSession接口,该接口在应用程序和数据库中间,代表着和数据库之间的一次连接,这次连接就是SqlSession对象。获取SqlSession对象需要由SqlSessionFactory来新建,SqlSessionFactory需要包含sql配置信息,所以SqlSessionFactoryBuilder来build。步骤二总结:SqlSessionFactoryBuilder(配置文件路径) -> SqlSessionFactory(openSession.) -> SqlSession.
  3. SqlSession只是给SqlSession一个接口,SqlSession不是sql的真正执行对象,SqlSession包含了Executor对象,Executor才是正真执行sql的对象。Executor对象封装了对数据库的所有操作,这些操作执行sql、处理结果集需要多个对象,这些对象统称为MappedStatement。步骤二总结:SqlSession --> Executor -> MappedStatement.

注:具体流程可以看Mybatis源码,步骤三简写了SqlSession与Executor之间调用关系,Mybatis框架用到了代理模式,具体基本调用顺序openSession() -> openSessionFromDataSource -> configuration.newExecutor、new DefaultSqlSession -> sqlSession.getMappe -> configuration.getMapper -> mapperRegistry.getMapper -> mapperProxyFactory.newInstance -> MapperProxy.invoke -> mapperMethod.execute -> DefaultSqlSession.selectOne --> BaseExecutor.query --> SimpleExecutor.doQuery --> SimpleStatementHandler.query --> DefaultResultSetHandler.handleResultSets(Statement stmt)->得到数据。
在这里插入图片描述

MyBatis主要成员及结构

MyBatis主要成员主要分为两类,一类是与配置相关,一块是与JDBC底层连接相关。

配置

配置类Configuration:所有信息都保存在里面。上面讲到Configuration包括了全局和映射配置文件,映射配置文件。映射配置文件包含了相关sql操作,MappedStatement封装了Map配置文件里的相关sql操做,通过SqlSource生成动态的sql语句,并封装到BoundSql中。ResultMap是Mapper中定义的自定义结果集

类与接口的层次关系
  • SqlSession:作为最顶层API,表示和数据库交互时的会话,完成数据库的增删改成功能
  • Executor:MyBatis的执行器,是MyBatis调度的核心,负责sql语句的生成,和查询缓存的维护。
  • StatementHandler:封装了JDBC所有的Statement操作。例如 :
    • ParameterHandler 来负责对用户所传的参数转化为JDBC Statement所需要的相关的参数
    • ResultSetHandler 将JDBC返回的ResultSet结果集转化成list型的集合
    • TypeHandler 用来负责JAVA类型和JDBC之间的类型转换和映射关系
      在这里插入图片描述

四、 配置

SqlSessionFactory

<transactionManager type=”jdbc”/>  可填jdbc和manager
		Jdbc 事务的处理和回滚交给jdbc	 
		Manager 事务的处理和回滚交给框架,比如spring
<dataSource type=”POOLED”> 数据源
<property name=”driver” value=”…”>
<property name=”url” value=”…”>
<property name=”nsername” value=”…”>
<property name=”password” value=”…”>

java 对象

  • 构建对象
  • 构建结构

创建JAVA对象和SQL语句映射关系配置文件

<mapper namespace=”com.jdbc.practice.GetUserInfo”>
<select id=”getUser” parameterType=”int” resultType=“com.jdbc.practice.User”>
	select id. userName, corp from user where id =#{id}
</select>

映射文件写入configuration

<mappers>
	<mapper resource="com./.../.../.../userMapper.xml">
</mappers>

五、完成数据库查询

流程(映射文件)

  1. 加载配置文件
    • 应用配置文件
    • 关联映射文件
  2. sqlSession
    • 生成SqlSessionFactory
    • 获取SqlSession
  3. 执行查询
    • Session执行sql

示例(映射文件)

接口定义
public interface GetUserInfo { 
	public User getUser(int id);
}

1. 声明配置文件的目录
String resource = "conf.xml";
2. 加载应用配置⽂文件
InputStream is = HelloMyBatis.class.getClassLoader()
.getResourceAsStream(resource);
3. 创建SqlSessonFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(is);
4. 获取Session
SqlSession session = sessionFactory.openSession();
try {
	5. 获取操作类
	GetUserInfo getUserInfo =
	session.getMapper(GetUserInfo.class);

6. 完成查询操作
User user = getUserInfo.getUser(11);
System.out.println(user.getId() + " " + user.getUserName() + " "+ user.getCorp());
} finally {
	7.关闭Session
	session.close();
}

流程(注解)

  1. 加载配置文件
    • 应用配置文件
  2. sqlSession
    • 生成SqlSessionFactory
    • 获取SqlSession
  3. 执行查询
    • Session执行sql

示例(注解)

接口定义
public interface GetUserInfoAnnotation {
@Select("select * from user where id = #{id}")
public User getUser(int id);
}

public static void main(String[] args) {
1. 声明配置文件的目录
String resource = "confAnnotation.xml";
2. 加载应用配置文件
InputStream is = HelloMyBatisAnnotation.class.getClassLoader()
.getResourceAsStream(resource);
3. 创建SqlSessonFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(is);
Configuration conf = sessionFactory.getConfiguration();
conf.addMapper(GetUserInfoAnnotation.class);
// 4. 获取Session
SqlSession session = sessionFactory.openSession();
try {
// 5. 获取操作类
GetUserInfoAnnotation getUserInfo =
session.getMapper(GetUserInfoAnnotation.class);
// 6. 完成查询操作
User user = getUserInfo.getUser(11);
System.out.println(user.getId() + " " + user.getUserName() + "
"
+ user.getCorp());
} finally {
// 7.关闭Session
session.close();
}

配置文件示例

<?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" />
<!-- 配置数据库连接信息 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/
cloud_study" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<mappers>//注解的方式无需用此标签
<mapper resource="com/micro/profession/mybatis/userMapper.xml" />
</mappers>
</configuration>

映射文件示例

注解方式不需要用到此文件。
<?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="com.micro.profession.mybatis.GetUserInfo">
<select id="getUser" parameterType="int"
resultType="com.micro.profession.mybatis.User">
select id ,userName,corp from user where id =#{id}
</select>
</mapper>

六、复杂映射关系

ResultMap

ResultMap 可以实现复杂查询结果到复杂对象关联关系的转化。

复杂关系分析

在这里插入图片描述

  • 学生和课程是多对多的映射关系。
  • 教师和课程是一对多的映射关系。
数据库表之间关系

除了学生、教师、课程三张数据表之外还需要一张学生课程数据表来记录学生和课程的之间关系。

学生表教师表课程表学生课程关联表
idididid
userNameteachernamecourseNameuser_id
corpteacher_idcourse_id
持久化类之间关系

三者之间的关系涉及到关联、容器、嵌套。

User.class 省略了@Getter @Setter 注意构造函数内容,无需courses
private int id;
private String userName;
private String corp;
private List<Course> courses; !
public User(Integer id, String userName, String corp) {
	this.userName = userName;
	this.id = id;
	this.corp = corp;
}

Teacher.class 省略了@Getter @Setter
private int id;
private String teacherName;

Course.class 省略了@Getter @Setter
private int id;
private String courseName;
private Teacher teacher;

复杂映射关系的映射文件

<?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="com.micro.profession.mybatis.resultMapTest.UserOp">
	<select id="getUser" parameterType="int" resultMap="UserMap">
		select u.id
		as userId,userName,courseName,corp,c.id as courseId,teacher.id as
		teacherId,teacherName from user u left
		join
		userCourse uc on u.id
		=uc.user_id left join course c on c.id =
		uc.course_id left join teacher
		on teacher.id = c.teacher_id where u.id
		= #{id}
	</select>
	<resultMap id="UserMap" type="com.micro.profession.mybatis.resultMapTest.User">
		<constructor>构造函数
			<idArg column="userId" javaType="int" />标记结果为ID能增加整体效能
			<arg column="userName" javaType="String" />注入到构造方法的一个普通结果
			<arg column="corp" javaType="String" />
		</constructor>
		<collection property="courses" ofType="com.micro.profession.mybatis.resultMapTest.Course"> 实现一对多的关联
			<id property="id" column="courseId" /> 标记结果为ID能增加整体效能
			<result property="courseName" column="courseName" /> 注入到字段或者JavaBean属性的普通结果
			<association property="teacher" column="teacher_id" javaType="com.micro.profession.mybatis.resultMapTest.Teacher"> 实现复杂类型之间的关联
				<id property="id" column="teacherId" /> 标记结果为ID能增加整体效能
				<result property="teacherName" column="teacherName" />注入到字段或者JavaBean属性的普通结果
			</association>
		</collection>
	</resultMap>
</mapper>

涉及sql语句解释

七、数据库连接池

MyBatis 3.0 内置连接池

文件配置

<dataSource type="POOLED">
	<property name="driver" value="com.mysql.jdbc.Driver" />
	<property name="url" value="jdbc:mysql://localhost/cloud_study" />
	<property name="username" value="root" />
	<property name="password" value="123456" />
</dataSource>

数据库连接生命周期

MyBatis中维护了一个类似于DBCP的连接池,其主要维护了两个连接队列,分别为 空闲连接活跃连接。数据库连接从上述两个队中获取。

声明周期流程图

在这里插入图片描述

连接池常用配置选项
选项功能
poolMaximumCheckoutTime获取连接时如果没有idleConnection同时activeConnection达到最大值,则从activeConnections列表第一个连接开始,检查是否超过poolMaximumCheckoutTime,如果超过,则强制使其失效,返回该连接。由于SQL执行时间受服务器配置、表结构不同,建议设置为预期最大SQL执行时间。
poolMaximumActiveConnections数据库最大活跃连接数,考虑到随着连接数的增加,性能可能达到拐点,不建议设置过大。
poolMaximumIdIeConnections最大空闲连接数,经验值建议设置与poolMaximum相同即可。
poolPingEnabled启用连接侦测,检查连接池中的连接是否为有效连接,默认关闭,建议启用,防止服务器端异常关闭,导致客户端错误。
poolPingQuery侦测SQL,建议使用select 1,开销小
poolPingConnectionsN0tUsedFor侦测时间,建议小于服务器端超时时间,MySQL默认超时8小时。
poolTimeToWait获取服务器端数据库连接的超时时间,如果超过该时间,则打印日志,同时重新获取。建议使用默认值20S。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值