简介

MyBatis是一个轻量级的ORM框架,它简化了对关系数据库的使用,开发人员可以在XML或注解中编写SQL来完成对数据库的操作。
如果完全使用XML方式,SQL语句可以集中维护,做到与Java代码完全隔离,便于对SQL调优。

原理及流程

  1. 加载配置:配置来源于两个地方,一是配置文件,一是Java代码的注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
  2. SQL解析:当API接口层接收到调用请求时,会接收到传入SQL的ID和传入对象(可以是Map、JavaBean或者基本数据类型),Mybatis会根据SQL的ID找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的SQL语句和参。
  3. SQL执行:将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。
  4. 结果映射:将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回。

技术盏

反射、jdk动态代理、Ognl表达式引擎、缓存

反射和动态代理

解析是将SQL或存储过程定义表述为Mybatis中对应对象的过程,例如将执行的Sql标签( , …)解析为 MappedStatement ;输入参数定义标签解析为 ParameterMap ;结果列定义标签解析为 ResultMap

Mybatis支持将一个类的方法映射到一个 mapper 文件里的对应 statement sql,将方法名与DML SQL标签的id对应起来,这样我们就可以透明地使用 interface 的方式结合了面向对象的方式来与数据库操作,这样做更趋近于面向对象的编程风格。其中用到jdbc动态代理原理,用 MapperProxy 动态代理了需要执行的接口方法,主要代理逻辑在 MapperMethod 中实现,负责用接口的名称以及方法名称找到解析好的 MappedStatement 然后调用 SqlSession 中对应的执行逻辑执行。

缓存

Mybatis的一级缓存是SqlSession级别。第一次执行select时候会发现sqlsession缓存没有记录,会去数据库查找,然后把结果保存到缓存,第二次同等条件查询下,就会从缓存中查找到结果。另外为了避免脏读,每次执行更新新增删除时候会清空当前sqlsession缓存。

二级缓存是namespace级别的。同一个namespace下的搜寻语句共享一个二级缓存。如果开启了二级缓存,则先从二级缓存中查找,查找不到则委托为SimpleExecutor查找,而它则会先从一级缓存中查找,查找不到则从数据库查找。

mybaits的二级缓存一般不怎么使用,默认一级缓存是开启的。

#基于注解方式的demo

CREATE TABLE `user` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`user_name` varchar(100) DEFAULT NULL,`create_time` int(11) DEFAULT NULL,`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;​
 <dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>1.4.3.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.1.1</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-dbcp2</artifactId><version>2.1.1</version></dependency></dependencies>

application.properties

project.name=mybatis
server.port=7005
management.port=7006jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123logging.level.root=info

mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 我们不会将这个Bean进行实例化,class属性中定义了PropertyPlaceholderConfigurer类,可以告诉Spring我们实际上要注册一个properties文件--><bean id="propertyFileConfigForDB"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location"><value>classpath:application.properties</value></property></bean><tx:annotation-driven transaction-manager="transactionManager"/><!-- 声明式事物控制 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 --><bean id="sqlSessionFactor" class="org.mybatis.spring.SqlSessionFactoryBean" primary="true"><property name="dataSource" ref="dataSource"/></bean><!-- DAO接口所在包名,Spring会自动查找其下的类 ,包下的类需要使用@MapperScan注解,否则容器注入会失败 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.test.dao.*"/><property name="sqlSessionFactoryBeanName" value="sqlSessionFactor"/></bean>
</beans>

主类上添加注解 @ImportResource({“classpath:mybatis.xml”}),以引入配置mybatis.xml

public class UserDo {public Long getId() {return id;}public void setId(Long id) {this.id = id;}private Long id;private String user_name;private Long create_time;private Integer age;public UserDo() {}public String getUser_name() {return user_name;}public void setUser_name(String user_name) {this.user_name = user_name;}public Long getCreate_time() {return create_time;}public void setCreate_time(Long create_time) {this.create_time = create_time;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}@MapperScan
public interface UserMapper {@Insert("insert into user (user_name,create_time,age) values ("+ "#{user_name},#{create_time},#{age})")@Options(useGeneratedKeys = true, keyProperty = "id")Long insertUser(UserDo userDo);@Delete("delete from user where id = #{id}")Long deleteUser( Long id);@Update("update user set user_name=#{user_name}, create_time=#{create_time},"+ " age=#{age} where id=#{id}")Long updateUser(UserDo userDo);@Select("select * from user where id=#{id}")UserDo selectUserById(Long id);
}public interface UserService {Long createUser(User user);Long deleteUser(Long id);Long updateUser(User user);User selectUser(Long id);
}@Service
public class UserServiceImpl implements UserService {private static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);@Resourceprivate UserMapper userMapper;@Overridepublic Long createUser(User user) {try {return userMapper.insertUser(new UserDo(user));} catch (Exception ex) {logger.error("exception occurred: {}", ex);}return null;}@Overridepublic Long deleteUser(Long id) {try {return userMapper.deleteUser(id);} catch (Exception ex) {logger.error("exception occurred: {}", ex);}return null;}@Overridepublic Long updateUser(User user) {try {return userMapper.updateUser(new UserDo(user));} catch (Exception ex) {logger.error("exception occurred: {}", ex);}return null;}@Overridepublic User selectUser(Long id){try {UserDo userDo =  userMapper.selectUserById(id);return new User(userDo);} catch (Exception ex) {logger.error("exception occurred: {}", ex);}return null;}
}

通过maven插件自动生成entity、mapper

<generatorConfiguration><classPathEntry location="etc\mybatis-generator\mysql-connector-java-5.1.46.jar"/><context id="DB2Tables" targetRuntime="MyBatis3"><plugin type="org.mybatis.generator.plugins.ToStringPlugin"/><plugin type="com.itfsw.mybatis.generator.plugins.BatchInsertPlugin"/><plugin type="com.xxx.finance.commons.service.mybatis.generator.plugin.MySQLPaginationPlugin"></plugin><commentGenerator><property name="addRemarkComments" value="true"/></commentGenerator><jdbcConnection driverClass="com.mysql.jdbc.Driver"connectionURL="jdbc:mysql://xx.xx.xxx.xxx:xxxx/risk_alpha_engine"userId="xxxxx" password="xxxxx"></jdbcConnection><javaModelGenerator targetPackage="com.xxx.fin.phecda.strategy.dal.entity" targetProject="src/main/java"/><sqlMapGenerator targetPackage="sql" targetProject="src/main/resources"/><javaClientGenerator targetPackage="com.xxx.fin.phecda.strategy.dal.mapper" targetProject="src/main/java"type="com.xxx.finance.commons.service.mybatis.generator.MySimpleJavaMapperGenerator"/><table tableName="sys_rule_element_rel" enableUpdateByPrimaryKey="false" enableDeleteByPrimaryKey="false" enableDeleteByExample="false"/><table tableName="flow_strategy_log" enableUpdateByPrimaryKey="false" enableDeleteByPrimaryKey="false" enableDeleteByExample="false"/><table tableName="sys_biz_flow_version" enableUpdateByPrimaryKey="true" enableDeleteByPrimaryKey="false" enableDeleteByExample="false"/></context>
</generatorConfiguration>
<dependencies><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.5</version><configuration><verbose>true</verbose><overwrite>true</overwrite><configurationFile>${basedir}/etc/mybatis-generator/generatorConfig.xml</configurationFile></configuration><dependencies><dependency><groupId>com.xxx.finance</groupId><artifactId>commons-service-mybatis</artifactId><version>1.4.1-SNAPSHOT</version></dependency><dependency><groupId>com.itfsw</groupId><artifactId>mybatis-generator-plugin</artifactId><version>1.0.5</version></dependency></dependencies></plugin></plugins></build>

sharding-sphere分表分库

https://tomoya92.github.io/2020/06/03/sharding-sphere-horizontal-split/

<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId><groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId><groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId><groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId><groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId><groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>

参考资料

入门+原理
https://zhuanlan.zhihu.com/p/34446308
https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247483937&idx=1&sn=85727e94ad3d1af1ef99cfefa420520c&chksm=ebd74320dca0ca367f869427202eb029bf3cf8dd4dc71dae26d925aaaabc2c8ea704735b3b87&scene=21###wechat_redirect

MyBatis原理浅析相关推荐

  1. Springboot整合redis实现缓存及其缓存运行原理浅析

    声明:小白,学习阶段,主要目的是为了记录学习过程,本文仅供参考,如有不足的地方欢迎指出讨论交流 本文基于Springboot2.1.3版本开发: 准备阶段 首先是pom.xml文件所需的依赖: < ...

  2. Seata 分布式事务的使用和原理浅析

    Seata 分布式事务的精简使用教程和原理浅析 一.说明 二.Seata 简介 2.1.Seata 是什么? 2.2.Seata 的整体架构 2.2.1.主要角色 2.2.2.整体架构和工作流程图 2 ...

  3. Python标准库queue模块原理浅析

    Python标准库queue模块原理浅析 本文环境python3.5.2 queue模块的实现思路 作为一个线程安全的队列模块,该模块提供了线程安全的一个队列,该队列底层的实现基于Python线程th ...

  4. Python标准库threading模块Condition原理浅析

    Python标准库threading模块Condition原理浅析 本文环境python3.5.2 threading模块Condition的实现思路 在Python的多线程实现过程中,在Linux平 ...

  5. 第一篇: 词向量之Word2vector原理浅析

    第一篇: 词向量之Word2vector原理浅析 作者 Aroundtheworld 2016.11.05 18:50 字数 1353 阅读 5361评论 1喜欢 9 一.概述 本文主要是从deep ...

  6. SPI及其工作原理浅析

    说明.文章摘自:SPI协议及其工作原理浅析 http://bbs.chinaunix.net/thread-1916003-1-1.html 一.概述. SPI, Serial Perripheral ...

  7. 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现

    本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论. MyBatis将数据缓存设计成两级结构,分为一级缓存 ...

  8. .NET1.1中预编译ASP.NET页面实现原理浅析[1]自动预编译机制浅析

    .NET1.1中预编译ASP.NET页面实现原理浅析[1]自动预编译机制浅析 .NET1.1中预编译ASP.NET页面实现原理浅析[1]自动预编译机制浅析 作者:&;nbsp来自:网络 htt ...

  9. LinkedList 的实现原理浅析

    转载自 LinkedList 的实现原理浅析 LinkedList内部结构 查看LinkedList的源码,发现其继承自AbstractSequentialList,实现了List,Deque,Clo ...

最新文章

  1. 2021.4.7 美团买菜后端开发实习生(二面)(含总结)(已oc)
  2. h5 解决ios端输入框失去焦点后页面不回弹或者底部留白问题
  3. python文档生成工具 sphinx 简介
  4. 用自然语言指导强化学习agent打游戏,这是斯坦福的最新研究
  5. VMware大会宋家瑜言虚拟化2015年方至巅峰
  6. 双眼融合训练一个月_视觉融合你知道多少
  7. windows server 2008 iis6.0 无法下载.exe
  8. linux7 修改服务启动项目命令,centos7服务部署flask项目
  9. c++输出重定向 linux,C++ stderr/stdout 重定向到文件
  10. python小孩的报酬_孩子做了家务,家长该不该支付“酬劳”呢?
  11. opencv训练样本分类器
  12. 最新小白详细描述在centos7.5上安装python3并使用Nginx+virtualenv+supervisor来部署tornado项目(整理集合结合实际)系列1
  13. 【转】sql server 订阅发布、快照发布(一)
  14. 前台ajax请求php后台返回成功却进error方法解决
  15. Matlab 多行屏蔽或注释方法
  16. X509证书信任管理器类的实现及应用
  17. 解决HC05蓝牙模块主从配对失败及AT模式设置方案
  18. hdu 1705[皮克定理]
  19. 厦门新车上牌经验分享
  20. HDMI接口简介---分辨率 时钟频率 lane速率计算

热门文章

  1. 【单片机仿真】(十七)控制转移类指令 — 调用及返回指令
  2. 地图无限放大服务器软件,BIGEMAP离线地图服务器
  3. 奥利给!!字体/颜色对话框这么豪横的解释,赶紧PICK一下吧!!
  4. 利用pearcmd.php本地文件包含(LFI)
  5. 【PyG】与networkx的图转换
  6. ZYNQ简介 | ZYNQ到底是什么?
  7. conda安装tensorflow和conda常用命令
  8. Trac 经验谈之(5)插件篇
  9. 行为识别之slowfast
  10. div overflow属性