織夢淘寶客網(wǎng)站/活動(dòng)營銷案例100例
😀前言
本篇博文是學(xué)習(xí)過程中的筆記和對于MyBatis底層機(jī)制的分析思路,希望能夠給您帶來幫助😊
🏠個(gè)人主頁:晨犀主頁
🧑個(gè)人簡介:大家好,我是晨犀,希望我的文章可以幫助到大家,您的滿意是我的動(dòng)力😉😉
💕歡迎大家:這里是CSDN,我總結(jié)知識(shí)的地方,歡迎來到我的博客,感謝大家的觀看🥰
如果文章有什么需要改進(jìn)的地方還請大佬不吝賜教 先在次感謝啦😊
文章目錄
- 自己實(shí)現(xiàn)MyBatis 底層機(jī)制[上]
- MyBatis 整體架構(gòu)分析
- Mybatis 核心框架示意圖
- 核心框架示意圖的解讀
- 搭建MyBatis 底層機(jī)制開發(fā)環(huán)境
- 1、創(chuàng)建Maven 項(xiàng)目nlc-mybatis
- 2、修改nlc-mybatis\pom.xml
- 3、創(chuàng)建數(shù)據(jù)庫和表
- 4、到此: 項(xiàng)目開發(fā)環(huán)境搭建完成
- Nlc-Mybatis 的設(shè)計(jì)思路
- Mybatis 的底層實(shí)現(xiàn)設(shè)計(jì)
- 1. 傳統(tǒng)方式操作數(shù)據(jù)庫
- 2.MyBatis操作數(shù)據(jù)庫的方式分析
- 自己實(shí)現(xiàn)MyBatis 底層機(jī)制
- 實(shí)現(xiàn)任務(wù)階段1- 完成讀取配置文件,得到數(shù)據(jù)庫連接
- 分析示意圖
- 代碼實(shí)現(xiàn)
- 完成測試
- 測試效果
- 實(shí)現(xiàn)任務(wù)階段2- 編寫執(zhí)行器,輸入SQL 語句,完成操作
- 分析示意圖
- 代碼實(shí)現(xiàn)
- 完成測試
- 😄總結(jié)
自己實(shí)現(xiàn)MyBatis 底層機(jī)制[上]
MyBatis 整體架構(gòu)分析
Mybatis 核心框架示意圖
核心框架示意圖的解讀
- mybatis 的核心配置文件
mybatis-config.xml: 進(jìn)行全局配置,全局只能有一個(gè)這樣的配置文件
XxxMapper.xml 配置多個(gè)SQL,可以有多個(gè)XxxMappe.xml 配置文件 - 通過mybatis-config.xml 配置文件得到SqlSessionFactory
- 通過SqlSessionFactory 得到SqlSession,用SqlSession 就可以操作數(shù)據(jù)了
- SqlSession 底層是Executor(執(zhí)行器), 有兩個(gè)重要的實(shí)現(xiàn)類基本執(zhí)行器和帶緩存功能的執(zhí)行器, 有很多方法
- MappedStatement 是通過XxxMapper.xml 中定義, 生成的statement 對象
- 參數(shù)輸入執(zhí)行并輸出結(jié)果集, 無需手動(dòng)判斷參數(shù)類型和參數(shù)下標(biāo)位置, 且自動(dòng)將結(jié)果集映射為Java 對象
搭建MyBatis 底層機(jī)制開發(fā)環(huán)境
1、創(chuàng)建Maven 項(xiàng)目nlc-mybatis
前面快速入門有創(chuàng)建步驟,這里不在描述。
2、修改nlc-mybatis\pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.nlc</groupId><artifactId>nlc-mybatis</artifactId><version>1.0-SNAPSHOT</version><!--定義編譯器 / source / target 版本即可--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><java.version>1.8</java.version></properties><!--引入必要的依賴--><dependencies><!--引入dom4j--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!--引入mysql依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><!--lombok-簡化entity/javabean/pojo開發(fā) --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.4</version></dependency><!--junit依賴--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
</project>
3、創(chuàng)建數(shù)據(jù)庫和表
CREATE DATABASE `nlc_mybatis`;
USE `nlc_mybatis`;
CREATE TABLE `monster` (`id` INT NOT NULL AUTO_INCREMENT,`age` INT NOT NULL,`birthday` DATE DEFAULT NULL,`email` VARCHAR(255) NOT NULL,`gender` TINYINT NOT NULL,`name` VARCHAR(255) NOT NULL,`salary` DOUBLE NOT NULL,PRIMARY KEY (`id`)
) CHARSET=utf8
INSERT INTO `monster` VALUES(NULL, 200, '2000-11-11', 'nmw@sohu.com', 1,'牛魔王', 8888.88)
4、到此: 項(xiàng)目開發(fā)環(huán)境搭建完成
Nlc-Mybatis 的設(shè)計(jì)思路
Mybatis 的底層實(shí)現(xiàn)設(shè)計(jì)
1. 傳統(tǒng)方式操作數(shù)據(jù)庫
-
得到Session對象
-
調(diào)用Executor的方法完成操作
-
Executor的連接是從Configuration獲取的
2.MyBatis操作數(shù)據(jù)庫的方式分析
- 得到Session
- 不用直接調(diào)用Executor的方法完成操作
- 通過MapperProxy獲取Mapper對象
- 調(diào)用Mapper的方法,完成數(shù)據(jù)庫的操作
- Mapper最終還是動(dòng)態(tài)代理方式,使用Executor的方法完成操作
- MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。
自己實(shí)現(xiàn)MyBatis 底層機(jī)制
實(shí)現(xiàn)任務(wù)階段1- 完成讀取配置文件,得到數(shù)據(jù)庫連接
通過配置文件,獲取數(shù)據(jù)庫連接。
分析示意圖
代碼實(shí)現(xiàn)
- 創(chuàng)建nlc-mybatis\src\main\resources\nlc_config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<database><!--配置連接數(shù)據(jù)庫的信息--><property name="driverClassName" value="com.mysql.jdbc.Driver"/><!--配置連接mysql-url1. jdbc:mysql 協(xié)議2. 127.0.0.1:3306 : 指定連接mysql的ip+port3. mybatis: 連接的DB4. useSSL=true 表示使用安全連接5. & 表示 & 防止解析錯(cuò)誤6. useUnicode=true : 使用unicode 作用是防止編碼錯(cuò)誤7. characterEncoding=UTF-8 指定使用utf-8, 防止中文亂碼8. 不要背,直接使用即可--><property name="url" value="jdbc:mysql://localhost:3306/nlc_mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/><property name="username" value="root"/><property name="password" value="123456"/>
</database>
- 創(chuàng)建nlc-mybatis\sqlsession\NlcConfiguration.java
public class NlcConfiguration {//屬性-類的加載器private static ClassLoader loader =ClassLoader.getSystemClassLoader();//讀取xml文件信息,并處理public Connection build(String resource) {Connection connection = null;try {//加載配置nlc_mybatis.xml 獲取到對應(yīng)的InputStreamInputStream stream = loader.getResourceAsStream(resource);SAXReader reader = new SAXReader();Document document = reader.read(stream);//獲取到nlc_mybatis.xml 的根元素 <database>Element root = document.getRootElement();System.out.println("root=" + root);//解析root元素,返回Connection connection = evalDataSource(root);} catch (Exception e) {e.printStackTrace();}return connection;}//方法會(huì)解析nlc_config.xml 信息,并返回Connection//eval: 評估/解析private Connection evalDataSource(Element node) {if (!"database".equals(node.getName())) {throw new RuntimeException("root 節(jié)點(diǎn)應(yīng)該是<database>");}//連接DB的必要參數(shù)String driverClassName = null;String url = null;String username = null;String password = null;//遍歷node下的子節(jié)點(diǎn),獲取屬性值for (Object item : node.elements("property")) {Element i = (Element) item;//i 就是 對應(yīng)property節(jié)點(diǎn)String name = i.attributeValue("name");String value = i.attributeValue("value");//判斷是否得到name 和 valueif (name == null || value == null) {throw new RuntimeException("property 節(jié)點(diǎn)沒有設(shè)置name或者value屬性");}switch (name) {case "url":url = value;break;case "username":username = value;break;case "driverClassName":driverClassName = value;break;case "password":password = value;break;default:throw new RuntimeException("屬性名沒有匹配到...");}}Connection connection = null;try {//要求JVM查找并加載指定的類到內(nèi)存中,此時(shí)將"com.mysql.jdbc.Driver" 當(dāng)做參數(shù)傳入,// 就是告訴JVM,去"com.mysql.jdbc"這個(gè)路徑下找Driver類,將其加載到內(nèi)存中。Class.forName(driverClassName);connection = DriverManager.getConnection(url,username,password);} catch (Exception e) {e.printStackTrace();}return connection; //返回Connection}}
完成測試
- 編寫nlc-mybatis\src\test\java\com\nlc\test\NlcMybatisTest.java
public class NlcMyBatisTest {@Testpublic void build() {NlcConfiguration nlcConfiguration = new NlcConfiguration();Connection connection = nlcConfiguration.build("nlc_mybatis.xml");System.out.println("connection--" + connection);}
}
測試效果
實(shí)現(xiàn)任務(wù)階段2- 編寫執(zhí)行器,輸入SQL 語句,完成操作
說明:通過實(shí)現(xiàn)執(zhí)行器機(jī)制,對數(shù)據(jù)表操作。
分析示意圖
說明:我們把對數(shù)據(jù)庫的操作,會(huì)封裝到一套Executor 機(jī)制中,程序具有更好的擴(kuò)展性,結(jié)構(gòu)更加清晰.
代碼實(shí)現(xiàn)
- 創(chuàng)建nlc-mybatis\src\main\java\com\nlc\entity\Monster.java
如果使用@Data注解需要全參構(gòu)造器可以添加@AllArgsConstructor,但是無參構(gòu)造器必須要顯示調(diào)用,否則會(huì)被全參構(gòu)造器覆蓋。
/*** Monster 和 monster表有映射關(guān)系* @Getter 就會(huì)給所有屬性 生成對應(yīng)的getter* @Setter 就會(huì)給所有屬性 生成對應(yīng)的setter* @ToString 生成 toString...* @NoArgsConstructor 生成無參構(gòu)造器* @AllArgsConstructor 生成要給全參構(gòu)造器* @Data 會(huì)生成上面除全參構(gòu)造器的所有注解* 如何選擇主要還是看自己需要*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Monster {private Integer id;private Integer age;private String name;private String email;private Date birthday;private double salary;private Integer gender;}
- 創(chuàng)建nlc-mybatis\src\main\java\com\nlc\nlcmybatis\sqlsession\Executor.java
public interface Executor {//泛型方法public <T> T query(String statement, Object parameter);
}
- 創(chuàng)建nlc-mybatis\src\main\java\com\nlc\nlcmybatis\sqlsession\NlcExecutor.java
public class NlcExecutor implements Executor {//屬性private NlcConfiguration nlcConfiguration =new NlcConfiguration();// 根據(jù) sql 查找結(jié)果@Overridepublic <T> T query(String sql, Object parameter) {//得到連接ConnectionConnection connection = getConnection();//查詢返回的結(jié)果集ResultSet set = null;PreparedStatement pre = null;try {pre = connection.prepareStatement(sql);//設(shè)置參數(shù), 如果參數(shù)多, 可以使用數(shù)組處理.pre.setString(1, parameter.toString());set = pre.executeQuery();//把set數(shù)據(jù)封裝到對象-monster//說明: 這里做了簡化處理//認(rèn)為返回的結(jié)果就是一個(gè)monster記錄//完善的寫法是一套反射機(jī)制.Monster monster = new Monster();//遍歷結(jié)果集, 把數(shù)據(jù)封裝到monster對象while (set.next()) {monster.setId(set.getInt("id"));monster.setName(set.getString("name"));monster.setEmail(set.getString("email"));monster.setAge(set.getInt("age"));monster.setGender(set.getInt("gender"));monster.setBirthday(set.getDate("birthday"));monster.setSalary(set.getDouble("salary"));}return (T) monster;} catch (Exception throwables) {throwables.printStackTrace();} finally {try {if (set != null) {set.close();}if (pre != null) {pre.close();}if (connection != null) {connection.close();}} catch (Exception throwables) {throwables.printStackTrace();}}return null;}//編寫方法,通過NlcConfiguration對象,返回連接private Connection getConnection() {Connection connection = nlcConfiguration.build("nlc_mybatis.xml");return connection;}
}
完成測試
- 修改nlc-mybatis\src\test\java\com\nlc\test\NlcMybatisTest.java , 增加測試方法
@Testpublic void query() {Executor executor = new NlcExecutor();Monster monster =executor.query("select * from monster where id=?", 1);System.out.println("monster-- " + monster);}
- 測試效果
😄總結(jié)
- 了解底層的機(jī)制可以幫助我們更好的學(xué)習(xí),閱讀優(yōu)秀的源碼可以增長我們的功力。
- 適當(dāng)?shù)膁ebug可以解決我們的疑惑,底層是一個(gè)非常龐大的集成,把握主干就可以了。
- 過于追根究底只會(huì)影響自己的心緒,會(huì)耗費(fèi)大量時(shí)間精力。
- 如果自己感興趣的話,可以多研究一下,會(huì)發(fā)現(xiàn)其中的樂趣,點(diǎn)到即止。
文章到這里就結(jié)束了,如果有什么疑問的地方請指出,諸大佬們一起來評論區(qū)一起討論😁
希望能和諸大佬們一起努力,今后我們一起觀看感謝您的閱讀🍻
如果幫助到您不妨3連支持一下,創(chuàng)造不易您們的支持是我的動(dòng)力🤞