MyBatis原理系列(一)-手把手帶你閱讀MyBatis源碼
MyBatis原理系列(二)-手把手帶你了解MyBatis的啟動流程
MyBatis原理系列(三)-手把手帶你了解SqlSession,SqlSessionFactory,SqlSessionFactoryBuilder的關(guān)系
MyBatis原理系列(四)-手把手帶你了解MyBatis的Executor執(zhí)行器
MyBatis原理系列(五)-手把手帶你了解Statement、StatementHandler、MappedStatement間的關(guān)系
MyBatis原理系列(六)-手把手帶你了解BoundSql的創(chuàng)建過程
MyBatis原理系列(七)-手把手帶你了解如何自定義插件
MyBatis原理系列(八)-手把手帶你了解一級緩存和二級緩存
MyBatis原理系列(九)-手把手帶你了解MyBatis事務(wù)管理機制
作為Java碼農(nóng),無論在面試中,還是在工作中都會遇到MyBatis的相關(guān)問題。筆者從大學開始就接觸MyBatis,到現(xiàn)在為止都是會用,知道怎么配置,怎么編寫xml,但是不知道Mybatis核心原理,一遇到問題就復(fù)制錯誤信息百度解決。為了改變這種境地,鼓起勇氣開始下定決心閱讀MyBatis源碼,并開始記錄閱讀過程,希望和大家分享。
1. 初識MyBatis
還記得當初接觸MyBatis時,覺得要配置很多,而且sql要單獨寫在xml中,相比Hibernate來說簡直不太友好,直到后來出現(xiàn)了復(fù)雜的業(yè)務(wù)需求,需要編寫相應(yīng)的復(fù)雜的sql,此時用Hibernate反而更加麻煩了,用MyBatis是真香了。因此筆者對MyBatis的第一印象就是將業(yè)務(wù)關(guān)注的sql和java代碼進行了解耦,在業(yè)務(wù)復(fù)雜變化的時候,相應(yīng)的數(shù)據(jù)庫操作需要相應(yīng)進行修改,如果通過java代碼構(gòu)建操作數(shù)據(jù)邏輯,這不斷變動的需求對程序員的耐心是極大的考驗。如果將sql統(tǒng)一的維護在一個文件里,java代碼用接口定義,在需求變動時,只用改相應(yīng)的sql,從而減少了修改量,提高開發(fā)效率。以上也是經(jīng)常在面試中經(jīng)常問到的Hibernate和MyBatis間的區(qū)別一點。
切到正題,Mybatis是什么呢?
Mybatis SQL 映射框架使得一個面向?qū)ο髽?gòu)建的應(yīng)用程序去訪問一個關(guān)系型數(shù)據(jù)庫變得更容易。MyBatis使用XML描述符或注解將對象與存儲過程或SQL語句耦合。與對象關(guān)系映射工具相比,簡單性是MyBatis數(shù)據(jù)映射器的最大優(yōu)勢。
以上是Mybatis的官方解釋,其中“映射”,“面向?qū)ο蟆?,“關(guān)系型”,“xml”等等都是Mybatis的關(guān)鍵詞,也是我們了解了Mybatis原理后,會恍然大悟的地方。筆者現(xiàn)在不詳述這些概念,在最后總結(jié)的時候再進行詳述。我們只要知道Mybatis為我們操作數(shù)據(jù)庫提供了很大的便捷。
2. 源碼下載
我們首先要從github上下載源碼,倉庫地址,然后在IDEA中clone代碼

在打開中的IDEA中,選擇vsc -> get from version control -> 復(fù)制剛才的地址

點擊clone即可

經(jīng)過漫長的等待后,代碼會全部下載下來,項目結(jié)果如下,框起來的就是我們要關(guān)注的核心代碼了。

每個包就是MyBatis的一個模塊,每個包的作用如下:

3. 一個簡單的栗子
不知道現(xiàn)在還有沒有同學知道怎么使用原生的JDBC進行數(shù)據(jù)庫操作,現(xiàn)在框架太方便了,為我們考慮了很多,也隱藏了很多細節(jié),因此會讓我們處于一個云里霧里的境地,為什么這么設(shè)計,這樣設(shè)計解決了什么問題,我們是不得而知的,為了了解其中奧秘,還是需要我們從頭開始了解。
接下來筆者將以兩個栗子來分別講講如何用原生的JDBC操作數(shù)據(jù)庫,以及如何使用MyBatis框架來實現(xiàn)相同的功能,并比較兩者的區(qū)別。
3.1 創(chuàng)建表
在此我們建了兩張表,一張是t_test_user用戶信息主表,一張是t_test_user_info用戶信息副表,兩張表通過member_id進行關(guān)聯(lián)。
DROP TABLE IF EXISTS `t_test_user`;
CREATE TABLE `t_test_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`member_id` bigint(20) NOT NULL COMMENT '會員id',
`real_name` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '真實姓名',
`nickname` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '會員昵稱',
`date_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`date_update` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
`deleted` bigint(20) DEFAULT '0' COMMENT '刪除標識,0未刪除,時間戳-刪除時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=42013 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='測試表';
DROP TABLE IF EXISTS `t_test_user_info`;
CREATE TABLE `t_test_user_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`member_id` bigint(20) NOT NULL COMMENT '會員id',
`member_phone` varchar(50) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '電話',
`member_province` varchar(50) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '省',
`member_city` varchar(50) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '市',
`member_county` varchar(50) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '區(qū)',
`date_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`date_update` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
`deleted` bigint(20) NOT NULL DEFAULT '0' COMMENT '刪除標識,0未刪除,時間戳-刪除時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用戶信息測試表';
3.2 使用Java JDBC進行操作數(shù)據(jù)庫
JDBC(Java Database Connectivity,簡稱JDBC)是Java中用來規(guī)范客戶端程序如何來訪問數(shù)據(jù)庫的應(yīng)用程序接口,提供了諸如查詢和更新數(shù)據(jù)庫中數(shù)據(jù)的方法。使用JDBC操作數(shù)據(jù)庫,一般包含7步,代碼如下。
public class JDBCTest {
/**
* 數(shù)據(jù)庫地址 替換成本地的地址
*/
private static final String url = "jdbc:mysql://localhost:3306/test?useUnicode=true";
/**
* 數(shù)據(jù)庫用戶名
*/
private static final String username = "test";
/**
* 密碼
*/
private static final String password = "test";
public static void main(String[] args) {
try {
// 1. 加載數(shù)據(jù)庫驅(qū)動
Class.forName("com.mysql.jdbc.Driver");
// 2. 獲得連接
Connection connection = DriverManager.getConnection(url, username, password);
// 3. 創(chuàng)建sql語句
String sql = "select * from t_test_user";
Statement statement = connection.createStatement();
// 4. 執(zhí)行sql
ResultSet result = statement.executeQuery(sql);
// 5. 處理結(jié)果
while(result.next()){
System.out.println("result = " + result.getString(1));
}
// 6. 關(guān)閉連接
result.close();
connection.close();
} catch (Exception e){
System.out.println(e);
}
}
}
3.3 使用Mybatis進行操作數(shù)據(jù)庫
3.3.1 新增mybatis-config.xml配置
在路徑src/main/resources/mybatis-config.xml新增配置,配置內(nèi)容如下
<?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>
<!--一些重要的全局配置-->
<settings>
<setting name="cacheEnabled" value="true"/>
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--<setting name="multipleResultSetsEnabled" value="true"/>-->
<!--<setting name="useColumnLabel" value="true"/>-->
<!--<setting name="useGeneratedKeys" value="false"/>-->
<!--<setting name="autoMappingBehavior" value="PARTIAL"/>-->
<!--<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>-->
<!--<setting name="defaultExecutorType" value="SIMPLE"/>-->
<!--<setting name="defaultStatementTimeout" value="25"/>-->
<!--<setting name="defaultFetchSize" value="100"/>-->
<!--<setting name="safeRowBoundsEnabled" value="false"/>-->
<!--<setting name="mapUnderscoreToCamelCase" value="false"/>-->
<!--<setting name="localCacheScope" value="STATEMENT"/>-->
<!--<setting name="jdbcTypeForNull" value="OTHER"/>-->
<!--<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>-->
<!--<setting name="logImpl" value="STDOUT_LOGGING" />-->
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--這邊可以使用package和resource兩種方式加載mapper-->
<!--<package name="包名"/>-->
<package name="com.example.demo.dao"/> -->
<mapper resource="./mapper/TTestUserMapper.xml"/>
</mappers>
</configuration>
3.3.2 新增mapper接口
新增src/main/java/com/example/demo/dao/TTestUserMapper.java 接口
package com.example.demo.dao;
import com.example.demo.entity.TTestUser;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface TTestUserMapper {
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table t_test_user
*
* @mbggenerated
*/
int deleteByPrimaryKey(Long id);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table t_test_user
*
* @mbggenerated
*/
int insert(TTestUser record);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table t_test_user
*
* @mbggenerated
*/
int insertSelective(TTestUser record);
int batchInsert(List<TTestUser> records);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table t_test_user
*
* @mbggenerated
*/
TTestUser selectByPrimaryKey(Long id);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table t_test_user
*
* @mbggenerated
*/
int updateByPrimaryKeySelective(TTestUser record);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table t_test_user
*
* @mbggenerated
*/
int updateByPrimaryKey(TTestUser record);
}
3.3.3 新增映射配置文件
src/main/resources/mapper/TTestUserMapper.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="com.example.demo.dao.TTestUserMapper">
<resultMap id="BaseResultMap" type="com.example.demo.entity.TTestUser">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="member_id" jdbcType="BIGINT" property="memberId" />
<result column="real_name" jdbcType="VARCHAR" property="realName" />
<result column="nickname" jdbcType="VARCHAR" property="nickname" />
<result column="date_create" jdbcType="TIMESTAMP" property="dateCreate" />
<result column="date_update" jdbcType="TIMESTAMP" property="dateUpdate" />
<result column="deleted" jdbcType="BIGINT" property="deleted" />
</resultMap>
<sql id="Base_Column_List">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
id, member_id, real_name, nickname, date_create, date_update, deleted
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
select
<include refid="Base_Column_List" />
from t_test_user
where id = #{id,jdbcType=BIGINT}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
delete from t_test_user
where id = #{id,jdbcType=BIGINT}
</delete>
<insert id="insert" parameterType="com.example.demo.entity.TTestUser">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
insert into t_test_user (id, member_id, real_name,
nickname, date_create, date_update,
deleted)
values (#{id,jdbcType=BIGINT}, #{memberId,jdbcType=BIGINT}, #{realName,jdbcType=VARCHAR},
#{nickname,jdbcType=VARCHAR}, #{dateCreate,jdbcType=TIMESTAMP}, #{dateUpdate,jdbcType=TIMESTAMP},
#{deleted,jdbcType=BIGINT})
</insert>
<insert id="insertSelective" parameterType="com.example.demo.entity.TTestUser">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
insert into t_test_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="memberId != null">
member_id,
</if>
<if test="realName != null">
real_name,
</if>
<if test="nickname != null">
nickname,
</if>
<if test="dateCreate != null">
date_create,
</if>
<if test="dateUpdate != null">
date_update,
</if>
<if test="deleted != null">
deleted,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=BIGINT},
</if>
<if test="memberId != null">
#{memberId,jdbcType=BIGINT},
</if>
<if test="realName != null">
#{realName,jdbcType=VARCHAR},
</if>
<if test="nickname != null">
#{nickname,jdbcType=VARCHAR},
</if>
<if test="dateCreate != null">
#{dateCreate,jdbcType=TIMESTAMP},
</if>
<if test="dateUpdate != null">
#{dateUpdate,jdbcType=TIMESTAMP},
</if>
<if test="deleted != null">
#{deleted,jdbcType=BIGINT},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.example.demo.entity.TTestUser">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
update t_test_user
<set>
<if test="memberId != null">
member_id = #{memberId,jdbcType=BIGINT},
</if>
<if test="realName != null">
real_name = #{realName,jdbcType=VARCHAR},
</if>
<if test="nickname != null">
nickname = #{nickname,jdbcType=VARCHAR},
</if>
<if test="dateCreate != null">
date_create = #{dateCreate,jdbcType=TIMESTAMP},
</if>
<if test="dateUpdate != null">
date_update = #{dateUpdate,jdbcType=TIMESTAMP},
</if>
<if test="deleted != null">
deleted = #{deleted,jdbcType=BIGINT},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKey" parameterType="com.example.demo.entity.TTestUser">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
update t_test_user
set member_id = #{memberId,jdbcType=BIGINT},
real_name = #{realName,jdbcType=VARCHAR},
nickname = #{nickname,jdbcType=VARCHAR},
date_create = #{dateCreate,jdbcType=TIMESTAMP},
date_update = #{dateUpdate,jdbcType=TIMESTAMP},
deleted = #{deleted,jdbcType=BIGINT}
where id = #{id,jdbcType=BIGINT}
</update>
</mapper>
3.3.5 新增實體類
package com.example.demo.entity;
import java.io.Serializable;
import java.util.Date;
public class TTestUser implements Serializable {
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column t_test_user.id
*
* @mbggenerated
*/
private Long id;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column t_test_user.member_id
*
* @mbggenerated
*/
private Long memberId;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column t_test_user.real_name
*
* @mbggenerated
*/
private String realName;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column t_test_user.nickname
*
* @mbggenerated
*/
private String nickname;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column t_test_user.date_create
*
* @mbggenerated
*/
private Date dateCreate;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column t_test_user.date_update
*
* @mbggenerated
*/
private Date dateUpdate;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column t_test_user.deleted
*
* @mbggenerated
*/
private Long deleted;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database table t_test_user
*
* @mbggenerated
*/
private static final long serialVersionUID = 1L;
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column t_test_user.id
*
* @return the value of t_test_user.id
*
* @mbggenerated
*/
public Long getId() {
return id;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column t_test_user.id
*
* @param id the value for t_test_user.id
*
* @mbggenerated
*/
public void setId(Long id) {
this.id = id;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column t_test_user.member_id
*
* @return the value of t_test_user.member_id
*
* @mbggenerated
*/
public Long getMemberId() {
return memberId;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column t_test_user.member_id
*
* @param memberId the value for t_test_user.member_id
*
* @mbggenerated
*/
public void setMemberId(Long memberId) {
this.memberId = memberId;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column t_test_user.real_name
*
* @return the value of t_test_user.real_name
*
* @mbggenerated
*/
public String getRealName() {
return realName;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column t_test_user.real_name
*
* @param realName the value for t_test_user.real_name
*
* @mbggenerated
*/
public void setRealName(String realName) {
this.realName = realName == null ? null : realName.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column t_test_user.nickname
*
* @return the value of t_test_user.nickname
*
* @mbggenerated
*/
public String getNickname() {
return nickname;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column t_test_user.nickname
*
* @param nickname the value for t_test_user.nickname
*
* @mbggenerated
*/
public void setNickname(String nickname) {
this.nickname = nickname == null ? null : nickname.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column t_test_user.date_create
*
* @return the value of t_test_user.date_create
*
* @mbggenerated
*/
public Date getDateCreate() {
return dateCreate;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column t_test_user.date_create
*
* @param dateCreate the value for t_test_user.date_create
*
* @mbggenerated
*/
public void setDateCreate(Date dateCreate) {
this.dateCreate = dateCreate;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column t_test_user.date_update
*
* @return the value of t_test_user.date_update
*
* @mbggenerated
*/
public Date getDateUpdate() {
return dateUpdate;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column t_test_user.date_update
*
* @param dateUpdate the value for t_test_user.date_update
*
* @mbggenerated
*/
public void setDateUpdate(Date dateUpdate) {
this.dateUpdate = dateUpdate;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column t_test_user.deleted
*
* @return the value of t_test_user.deleted
*
* @mbggenerated
*/
public Long getDeleted() {
return deleted;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column t_test_user.deleted
*
* @param deleted the value for t_test_user.deleted
*
* @mbggenerated
*/
public void setDeleted(Long deleted) {
this.deleted = deleted;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table t_test_user
*
* @mbggenerated
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", memberId=").append(memberId);
sb.append(", realName=").append(realName);
sb.append(", nickname=").append(nickname);
sb.append(", dateCreate=").append(dateCreate);
sb.append(", dateUpdate=").append(dateUpdate);
sb.append(", deleted=").append(deleted);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}
3.3.6 執(zhí)行查詢
@Slf4j
public class MyBatisBootStrap {
public static void main(String[] args) {
try {
// 1. 讀取配置
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 2. 創(chuàng)建SqlSessionFactory工廠
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3. 獲取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4. 獲取Mapper
TTestUserMapper userMapper = sqlSession.getMapper(TTestUserMapper.class);
// 5. 執(zhí)行接口方法
TTestUser userInfo = userMapper.selectByPrimaryKey(16L);
System.out.println("userInfo = " + JSONUtil.toJsonStr(userInfo));
// 6. 提交事物
sqlSession.commit();
// 7. 關(guān)閉資源
sqlSession.close();
inputStream.close();
} catch (Exception e){
log.error(e.getMessage(), e);
}
}
}
3.4 區(qū)別
發(fā)現(xiàn)沒有在寫MyBatis的時候,新增了dao, mapper.xml, entity, mybatis-config.xml等很多東西,工作量反而增大了。但是dao, mapper.xml, entity都是可以根據(jù)插件mybatis-generator生成的,我們也不用一一去創(chuàng)建,而且我們沒有涉及到原生JDBC中加載驅(qū)動,創(chuàng)建連接,處理結(jié)果集,關(guān)閉連接等等這些操作,這些都是MyBatis幫我們做了,我們只用關(guān)心提供的查詢接口和sql編寫即可。
如果使用原生的JDBC進行數(shù)據(jù)庫操作,我們需要關(guān)心如何加載驅(qū)動,如何獲取連接關(guān)閉連接,如何獲取結(jié)果集等等與業(yè)務(wù)無關(guān)的地方,而MyBatis通過“映射”這個核心概念將sql和java接口關(guān)聯(lián)起來,我們調(diào)用java接口就相當于可以直接執(zhí)行sql,并且將結(jié)果映射為java pojo對象,這也是我們開頭說的“映射”,“面向?qū)ο蟮摹钡脑蛄恕?/p>
4. 總結(jié)
這篇文章簡單的介紹了下MyBatis的基本概念,并提供了簡單的栗子,接下來幾篇文章打算寫下Mybatis的啟動流程,讓我們更好的了解下mybatis的各模塊協(xié)作。