标签:driver 表数据 oct 代理 lca class imp param 实现类
MyBatis
和Hibernate
一样,是一个优秀的持久层框架。已经说过很多次了,原生的jdbc
操作存在大量的重复性代码(如注册驱动,创建连接,创建statement
,结果集检测等)。框架的作用就是把这些繁琐的代码封装,这样可以让程序员专注于sql
语句本身。
MyBatis
通过XML
或者注解的方式将要执行的sql
语句配置起来,并通过java
对象和sql
语句映射成最终执行的sql
语句。最终由MyBatis
框架执行sql
,并将结果映射成java
对象并返回。
我们大致了解一下Mybatis
的执行流程,结合案例工程来了解一下他是怎么工作的,后面将通过一步步的分析源码的方式进行深一步的了解
包含全局配置文件和映射文件。全局配置文件包含来数据源、日志、事务等信息,映射文件包含来SQL
执行相关的信息
XmlConfigBuilder
加载配置信息,例如properties
外部文件,alias
别名,plugins
插件等信息XmlMapperBuilder
加载Mapper
配置文件信息mapper
内的信息。XmlStatementBuilder
处理标签为select
|insert
|update
|delete
的语句,最终调用addMappedStatement
方法,将mapper
配置文件中的每一条SQL
语句封装成mappedStatement
对象,作为value
保存在HashMap
集合中;addLoadedResource
使用HashSet
集合存放mybatis
的mapper.xml
映射文件路径地址;bindMapperForNamespace()方法
,通过namespace
使用Java
反射机制找到mapper
接口,再调用addMapper()
方法,判断是否是接口类型,是否注册过(注册过则抛出异常)其中mapperRegistry
通过HashMap
保存mapper
接口,【key:接口;value:MapperProxyFactory】
openSession()
方法,执行newExecutor()
方法创建执行器;SimpleExecutor
简单执行器,再判断是否开启了二级缓存,默认是开启的,就会去创建CacheExecutor
缓存执行器interceptorChain.pluginAll()
方法,责任链设计模式,底层使用动态代理技术,使开发者可以自定义插件开发,只需要实现Interceptor
接口,并指定想要拦截的方法签名即可,最后返回执行器;getMapper()
方法,最终执行mapperProxyFactory.newInstance(sqlSession)
方法创建代理类MapperProxy
;MapperProxy
代理类的invoke()
方法;mapper
接口是否有实现类,显然我们没有实现类,则调用cacheMapperMethod()
方法去缓存中获取要代理的方法method
;cacheMapperMethod()
方法先去查找缓存中有没有,没有的话将mapper
配置文件中配置的SQL
语句和对应的mapper
接口方法进行关联并放入map
缓存中,后期直接走缓存了,最后执行execute()
方法;execute()
方法,最终调用select*()
方法;selectList()
方法,调用getMapperStatement()
方法获取对应的SQL
语句;query()
方法进行查询,判断如果开启了二级缓存并且配置了二级缓存存储介质(Redis,EhCache..)
则先走二级缓存中查询数据,第一次查询是没有缓存数据的,则刷新缓存配置,清除缓存。sessionFactory
)中没有查询到数据,就回去执行BaseExecutor
去查询 HashMap
一级缓存中(sqlSession
)是否有缓存数据,一级缓存(PerpetualCache
)存放在内存中的,同理也是没有的,最后查询数据库DBmybatis组件及mysql驱动
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
原始表数据
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for blog
-- ----------------------------
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`mobile` varchar(11) COLLATE utf8mb4_general_ci DEFAULT NULL,
`age` int(2) DEFAULT NULL,
`email` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of blog
-- ----------------------------
BEGIN;
INSERT INTO `person` VALUES (1, ‘wujiwen‘, ‘13011111111‘, 20, ‘jiwenwu@outlook.com‘);
INSERT INTO `person` VALUES (2, ‘mybatis‘, ‘13100000000‘, 10, ‘service@mybatis.com‘);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
全局配置文件信息mybatis-config.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>
<properties resource="jdbc.properties"/>
<typeAliases>
<typeAlias type="cn.wujiwen.bean.Person" alias="person"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="PersonMapper.xml"/>
</mappers>
</configuration>
数据源信息
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis
username=root
password=passw0rd
映射文件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">
<mapper namespace="cn.wujiwen.mapper.PersonMapper">
<insert id="insert" parameterType="person" keyColumn="id" keyProperty="id">
insert into person (nickname,mobile,age,email) values (#{nickname},#{mobile},#{age},#{email});
</insert>
<update id="update" parameterType="person">
update person
<set>
<if test="nickname != null">
nickname = #{nickname},
</if>
<if test="mobile != null">
mobile = #{mobile},
</if>
<if test="age != null">
age = #{age},
</if>
<if test="email != null">
email = #{email},
</if>
</set>
where id = #{id}
</update>
<delete id="delete">
delete from person where id = #{id}
</delete>
<select id="listPerson" resultType="person">
select * from person;
</select>
<select id="getPerson" resultType="person">
select * from person where id = #{id}
</select>
</mapper>
Mapper接口
public interface PersonMapper {
int insert(Person person);
int update(Person person);
int delete(Integer id);
List<Person> listPerson();
Person getPerson(Integer id);
}
/**
* Desc:
*
* @author wujw
* @email jiwenwu@outlook.com
* @date 2021/4/2
*/
public class MybatisStarted {
@Test
public void test() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
// 指定key获取sql
Person person = ((Person) session.selectOne("cn.wujiwen.mapper.PersonMapper.getPerson", 1));
System.out.println(person);
// 通过代理方式
PersonMapper mapper = session.getMapper(PersonMapper.class);
List<Person> personList = mapper.listPerson();
System.out.println(personList);
}
}
标签:driver 表数据 oct 代理 lca class imp param 实现类
原文地址:https://www.cnblogs.com/wujiwen/p/14714375.html