MyBatis的原理配置使用高级映射和代理机制和缓存机制
Posted 在炮火中前进
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis的原理配置使用高级映射和代理机制和缓存机制相关的知识,希望对你有一定的参考价值。
文章目录
一、MyBatis介绍
- 官网中给出的解释是:
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。 - MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
二、MyBatis原理
- 如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
- 从XML文件中构建SqlSessionFactory。每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
- 从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 但也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 file:// URL 构造的输入流。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- 从 SqlSessionFactory 中获取 SqlSession;
try (SqlSession session = sqlSessionFactory.openSession())
Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
使用和指定语句的参数和返回值相匹配的接口(比如 BlogMapper.class),现在你的代码不仅更清晰,更加类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。
例如:
try (SqlSession session = sqlSessionFactory.openSession())
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
三、MyBatis的配置
- 除了给定MyBatis依赖之外,还要连接数据库,那就需要再导入数据库驱动:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
1、配置全局配置文件
- 首先在创建的项目中找到resource;
如果没有那就创建一个新建一个包,包名设置为resource;然后鼠标右键点击依次点击如下图,将这个包设置为Resource Root;
- 在这个resource下新建一个xml类型的文件,
打开文件在MyBatis官网中找到配置信息,然后再根据需要做出一点修改;
<?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:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
- 在main目录的java下创建POJO类,即创建一个包,命名为POJO,然后新建一个类为:Student.java,与数据库中的Student表数据映射为student对象,给定数据库中的属性名,注意属性名要与数据库中的属性要一一对应;
public class Student
private Integer SID;//学生ID
private String Sname;//学生姓名
private String Ssex;//学生性别
private Integer Sage;//学生年龄
//省略getter和setter方法
- 然后再POJO包同一位置上新建一个mapper包,这个包用来存放我们创建的Mapper接口的文件;
public interface StudentMapper
Student selectStudentById(Integer id);//通过学生的ID来进行检索
- 配置Mapper的xml文件,即在resource资源的目录下创建一个mapper包,在这个包下来存放我们创建的Mapper的xml文件;
<?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命令空间:给定接口文件的全路径-->
<mapper namespace="com.example.springBootDemo.TestMabits.mapper.StudentMapper">
<!--
当ResultType无法完成某些字段映射时,需要resultMap进行显性映射
resultMap标签主要用来显性指定返回映射关系
id:必填,表示去名称,可以随便取
type:必填,指定显性映射的java类的全限定名
id标签:指定主键映射关系,ID标签一般使用一次指定主键即可
result:指定非主属性映射关系,可以多次使用
property:指定java类中属性名(必填
column:指定数据库中的属性名称(必填
jdbcType:指定数据库中当前属性类型(选填
typeHandler:如果是有自定义类型处理器需要在这里指定自定义类型处理器的
-->
<resultMap id="studentMap" type="student">
<id property="SID" column="SID"/>
<result property="Sname" column="Sname"/>
<result property="Ssex" column="Ssex"/>
<result property="Sage" column="Sage"/>
</resultMap>
<!--
select标签是查询操作标签
id属性:(必填的)Statement的id,必填的,和接口文件中的方法名保持一致
parameterType:表述输入参数的类型(String,pojo,Integer)
resultType:(必填)表示输出参数的类型(String,pojo,Integer)还可以返回resultMap类型(返回的是hashmap)两种类型二选一
#XXX:表示占位符 XXX:接口方法中的参数名称
-->
<select id="selectStudentById" parameterType="int" resultType="com.example.springBootDemo.TestMabits.pojo.StudentA">
select * from Student where SID =#sid
</select>
<!-- id:在空间命名具有唯一性,和方法名保持一致
parameterType:指定入参的类型,可以是类的全限定名或者
-->
<insert id="insertStudent" flushCache="true" parameterType="student"/>
<select id="selectAllStudents" resultType="com.example.springBootDemo.TestMabits.pojo.Student">
select * from Student;
</select>
</mapper>
- 将mapper.xml文件的映射路径配置到全局配置文件中;
<!--映射文件-->
<mappers>
<!--resource属性,指定mapper.xml文件的路径-->
<mapper resource="mapper/StudentMapper.xml"/>
</mappers>
- 然后再新建一个测试类,用来通过java代码执行查询操作;
package com.example.springBootDemo.TestMabits;
import com.example.springBootDemo.TestMabits.mapper.StudentMapper;
import com.example.springBootDemo.TestMabits.pojo.Student;
import org.apache.ibatis.annotations.Delete;
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;
import java.util.List;
import java.util.Properties;
public class MybatisDemo
public static void main(String[] args) throws IOException
//1、创建SQLSessionFactory对象
//1.读取全局配置文件
String path="mybatis_config.xml";
//通过Resource获取文件流
InputStream resourceAsStream = Resources.getResourceAsStream(path);
//创建会话工厂,通过SQLSessionFactoryBUilder来创建
Properties properties = new Properties();
properties.setProperty("username","root");
properties.setProperty("password","123456");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream,properties);
// 创建会话,会话工厂是用来读取全局配置文件,通过builder类来创建
// 通过读取配置文件来创建实例,一般配置文件读取依次即可
// 对数据库CRUD操作
// SQLSession是线程不安全的,将其设置为方法的局部变量
// 以及缓存是基于SQLSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通过代理模式创建代理类
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
// Student student = studentMapper.selectStudentById(4);
// System.out.println(student);
List<Student> students=studentMapper.selectAllStudents();
for (Student s:students)
System.out.println(s);
运行结果:
- MyBatis的操作流程
- 配置MyBatis的全局配置文件(数据源,mapper映射)
- 创建SQLSessionFactory对象;
- 通过SQLSessionFactory创建SQLSession对象;
- 通过SQLSession来操作数据库CRUD操作;
- 关闭SQLSession资源;
2、XML配置
- MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
1、Properties
- 这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
- 在其中对应的属性可以用来提花为需要的动态配置的属性值,比如:
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="$username"/>
<property name="password" value="$password"/>
</dataSource>
- 这个例子中的 username 和 password 将会由 properties 元素中设置的相应值来替换
如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:
- 首先读取在 properties 元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
- 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。
2、setting
- 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。
3、typeAliases(类型别名)
- 类型别名是Java类型的短名称,和XML配置有关,存在是在于用来减少类全限定名的冗余,在mapper.xml中,会有很多的Statement,Statement需要的parameterType指定入参类型,需要resultType执行输出参数类型,如果是指定类型需要书写全限定名,不方便开发,可以通过类型别名,较少代码冗余
<!--类型别名-->
<typeAliases>
<!--单个类型定义别名: type:pojo全路径 alias:别名的名称-->
<typeAlias type="com.tulun.Mybatis.pojo.Student" alias="student"/>
<!--批量的别名定义 package:指定包名,将包下的所有pojo类定义别名,别名是类型(首字母大写或者小写都可以)-->
<package name="com.tulun.Mybatis.pojo"/>
</typeAliases>
4、Mappers
- 映射器
<mappers>
<!--单个文件映射:resource属性一次加载一个文件,
指定xml文件位置,通过namespace来查找mapper接口文件-->
<mapper resource="mapper/StudentMapper.xml"/>
<!--class方式映射:通过mapper接口映射单个文件,
遵循规则:mapper.java和mapper.xml放在同一个目录下,且命名相同-->
<!--<mapper class="com.tulun.Mybatis.mapper.StudentMapper"/>-->
<!--批量mapper的接口扫描规则
遵循规则:mapper.java和mapper.xml放在同一个目录下,且命名相同-->
<!--<package name="com.tulun.Mybatis.mapper"/>-->
</mappers>
- MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
3、标签详解
1、select标签
<!--
查询操作是select标签
id属性:(必填的)Statement的id是唯一标识,和接口文件中的方法名保持一致
parameterType:表示输入参数的类型(Pojo,Integer,String...)入参类型也可以是parameterMap(hashMap)两种类型二选1
resultType(必填):表示输出参数的类型(Pojo,Integer,String) 返回类型也可以是resultMap(hashMap)两种类型二选1
#XXX:表示占位符 XXX:接口方法中的参数名称
-->
<select id="selectStudentById" parameterType="int" rresultType="student">
select * from student where SID =#sid
</select>
2、insert标签
<!--
插入操作是insert标签
id属性:(必填的)Statement的id是唯一标识,和接口文件中的方法名保持一致
parameterType:(可选操作)表示输入参数的类型(Pojo,Integer,String...)入参类型也可以是parameterMap(hashMap)两种类型二选1
useGeneratedKeys:开启主键回写
keyColumn:指定数据库的主键
keyProperty:主键对应的pojo类属性名
-->
<insert id="testInsert" parameterMap="" useGeneratedKeys="true" keyColumn="" keyProperty=""
3、update标签
<!--
变更操作是update标签
id属性:(必填的)Statement的id是唯一标识,和接口文件中的方法名保持一致
parameterType:(可选操作)表示输入参数的类型(Pojo,Integer,String...)入参类型也可以是parameterMap(hashMap)两种类型二选1
useGeneratedKeys:开启主键回写
keyColumn:指定数据库的主键
keyProperty:主键对应的pojo类属性名
-->
<update id="testUpdate" >
</update>
4、delete标签
<!--
删除操作是delete标签
id属性:(必填的)Statement的id是唯一标识,和接口文件中的方法名保持一致
parameterType:(可选操作)表示输入参数的类型(Pojo,Integer,String...)入参类型也可以是parameterMap(hashMap)两种类型二选1
-->
<delete id="testdelete">
</delete>
四、MyBatis的使用
1、MyBatis中接口绑定的两种实现方式
- 通过注解绑定:就是在接口的方法上加上@Select、@update等注解,里面包含SQL语句进行绑定;
- 通过XML里面写SQL进行绑定,需要指定xml映射文件里的namespace必须为接口的全路径
语句比较简单时,使用注解绑定,当SQL语句比较复杂是,用xml绑定,一般使用xml比较多;
2、XML方式(使用步骤)
MyBatis的强大之处在于自定义SQL语句,映射器的xml文件方式相比JDBC简单,节省代码量
1、创建Mapper.java接口文件
public interface StudentMapper
Student selectStudentById(Integer sid);
2、创建Mapper.xml配置文件
<?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"&Mybatis常用类原理
-
功能:将java对象映射城sql语句,将结果集转化成java对象。将容易变化的放在配置文件中,不变的通过Mybatis管理。
-
完成:1.根据JDBC规范建立数据库的连接;
2.通过反射打通java对象与数据库参数转化的关系。
-
原理:动态代理和反射机制。
动态代理中用到JDK动态代理和CGLIB代理。
这两者的区别是,JDK动态代理是接口的,CGLIB代理是对于类的。
Mybatis中这两种代理都用到过,Mapper中用到的是JDK动态代理,在延迟加载的时候用到CGLIB代理。
1.读取配置到Configuration对象,并使用相应对象去创建SqlSessionFactory;
2.通过SqlSessionFactory拿到SqlSession进行增删改查方法。
SqlSessionDaoSupport:
1、SqlSessionDaoSupport 是 一 个 抽象 的支 持 类, 用来 为你 提供 SqlSession 。
1
2
3
4
5
6
7
8
9
10
11
12
13
@Autowired
@Override
public
void
setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
// TODO Auto-generated method stub
super
.setSqlSessionFactory(sqlSessionFactory);
}
//spring配置
<!-- 配置sqlSessionFactory -->
<bean id=
"sqlSessionFactory"
class
=
"org.mybatis.spring.SqlSessionFactoryBean"
>
<property name=
"dataSource"
ref=
"dataSource"
/>
<property name=
"configLocation"
value=
"classpath:mybatis.cfg.xml"
></property>
</bean>
<wiz_tmp_tag class="wiz-block-scroll">
2、调 用 getSqlSession()方法你会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法
3、持久层未继承SqlSessionDaoSupport,需要注入类
1
2
@Autowired
private
SqlSessionTemplate sqlSession;
且配置
1
2
3
<bean id=
"sqlSessionTemplate"
class
=
"org.mybatis.spring.SqlSessionTemplate"
>
<constructor-arg index=
"0"
ref=
"sqlSessionFactory"
/>
</bean>
涉及涉及模式:
Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;
工厂模式,例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;
单例模式,例如ErrorContext和LogFactory;
代理模式,Mybatis实现的核心,比如MapperProxy、ConnectionLogger,用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果;
组合模式,例如SqlNode和各个子类ChooseSqlNode等;
模板方法模式,例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler;
适配器模式,例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;
装饰者模式,例如Cache包中的cache.decorators子包中等各个装饰者的实现;
迭代器模式,例如迭代器模式PropertyTokenizer;
以上是关于MyBatis的原理配置使用高级映射和代理机制和缓存机制的主要内容,如果未能解决你的问题,请参考以下文章
Mybatis Mapper接口是如何找到实现类的-源码分析
JavaLearn#(28)MyBatis高级:无级联查询级联查询(立即加载结果映射延迟加载)多表连接查询MyBatis注解MyBatis运行原理面试题