Mybatis入門
MyBatis和Hibernate一樣,是一個優秀的持久層框架,已經說過很多次了,原生的jdbc操作存在大量的重復性代碼(如注冊驅動,創建連接,創建statement,結果集檢測等),框架的作用就是把這些繁瑣的代碼封裝,這樣可以讓程式員專注于sql陳述句本身,
MyBatis通過XML或者注解的方式將要執行的sql陳述句配置起來,并通過java物件和sql陳述句映射成最終執行的sql陳述句,最終由MyBatis框架執行sql,并將結果映射成java物件并回傳,
Mybatis的執行流程
我們大致了解一下Mybatis的執行流程,結合案例工程來了解一下他是怎么作業的,后面將通過一步步的分析原始碼的方式進行深一步的了解
1、讀取Mybatis配置資訊
包含全域組態檔和映射檔案,全域組態檔包含來資料源、日志、事務等資訊,映射檔案包含來SQL執行相關的資訊
2、獲取SqlSessionFactory工廠
- 通過
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】
3、獲取SqlSession
- 進入
openSession()方法,執行newExecutor()方法創建執行器; - 先創建
SimpleExecutor簡單執行器,再判斷是否開啟了二級快取,默認是開啟的,就會去創建CacheExecutor快取執行器 - 執行
interceptorChain.pluginAll()方法,責任鏈設計模式,底層使用動態代理技術,使開發者可以自定義插件開發,只需要實作Interceptor介面,并指定想要攔截的方法簽名即可,最后回傳執行器;
4、操作Mapper介面
- 呼叫
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)存放在記憶體中的,同理也是沒有的,最后查詢資料庫DB
5、封裝結果
案例
1、資料及Jar包準備
mybatis組件及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, '[email protected]');
INSERT INTO `person` VALUES (2, 'mybatis', '13100000000', 10, '[email protected]');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
2、組態檔資訊
全域組態檔資訊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="https://www.cnblogs.com/wujiwen/p/${driver}"/>
<property name="url" value="https://www.cnblogs.com/wujiwen/p/${url}"/>
<property name="username" value="https://www.cnblogs.com/wujiwen/p/${username}"/>
<property name="password" value="https://www.cnblogs.com/wujiwen/p/${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 [email protected]
* @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);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/281375.html
標籤:Java
