MyBatis For .NET学习笔记[3]:工作原理解析

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

上篇中说道MyBatis的前身是IBatis演化而来.其实IBatis发展到今天已经有9年的历史.当然目前最新版本是IBatis 3.0发布于2009 
年7月. 分别演化出不同的Java和.NET版本. 从3.0发布至今为止尚没有做下一个版本的更新.官方也并没提出下一个版本的更新计划.但这并不妨碍我们去进一步去探究MyBatis For .NET内部工作的原理.

其实在写这篇MyBatis原理时 刚开始的思路想从MyBatis插入一条记录过程来探讨MyBatis是如何解析SQL语句并执行一个Entity Object Mapping 到DataTale过程. 下午和一个同事做了一下交流.他提出一个看法是"你这样做还是教别人如何去用MyBatis的API.那只是MyBatis定义的一套规则而不是真正原理." 这句话仿佛提醒了我换一个角度来对MyBatis在设计Mapping时原理重新解析.我们应该从MyBatis实现整个Mapping过程细节泥沼之中跳出来.专注更多细节只会让我们离MyBatis设计初衷背离的越远.

后来在Code Of Google获得一本推荐IBatis原著<<IBatis in Action>> PDF文档[DownLoad Link]作者正好是IBatis开源项目发起人[CLINTON BEGIN]/[BRANDON GOODIN]./[LARRY MEADORS]. PDF Document中IBatis团队在How It Work?章节中详细阐述IBatis工作原理.这时目前为止找到官方最为详细的回应. 如下结合BUI项目将部分翻译其中片段.

上篇打该从CRUD的操作学会如何简单使用IBatis框架.可以看到它Mapping工作中核心的对象对应关系不是EntityModel实体对应关系型数据库中DataTable 而是EntityModel实体隐射SQL Statement.在来回归到What Exactly IS MyBatis?这个问题上.我们先把这些细节撇开来看一下设计MyBatis的初衷.

MyBatis作为一个独立的ORM框架.当然它的核心就是DataMApper数据关系之间的映射.当然针对映射层Martin Fowler大叔在他的《Patterns of Enterprise Application Architecture》一书中针对Data Mapper做了一次经典的描述:

一个映射层,在对象和数据库间传递数据,并保持两者与映射层本身相独立.

做一张图来说明DataMapper层次之间关系:

Martin Fowler大叔阐述提到两个特点:

[1]DataMapper Layer是相对Relation DataBase和Entity Model Layer是独立的

[2]DataMapper主要职能是实现Relation DataBase和Entity Model 之间数据交互.

谈到ORM工具.不得不提的是Nhibernate.但是这里有两个概念 数据映射[Data Mapping]和元数据映射[Metadata Mapping].而元数据映射恰恰体现ORM实现的根本依据. 这在Nhibernate中体现很明显.例如Nhibernate中定义一个EntityModel-Customer类时实现隐射的关联方式常常是建立指定具体的Customer类字段与对应数据库DataTAble表Fild之间.也就是说它将数据库的元数据映射到类的元数据.数据库表每个列都与实体类属性字段建立映射.

如上看到Nhibernate框架所采取的映射方式.而MyBatis则不同.它不是直接在类与数据表或字段与列之间进行关联,而是把SQLStatement 语句的参数[parameter]和返回结果[result]映射至类.其实从图1就可以看出MyBatis处于数据库表与实体对象层之间的中间层. 当我们需要修改时大部分工作集中MyBatis中来.而无需修改数据库表结构和实体对象结构.这种松散耦合.SQL 其实这种核心还是建立在SQL Statement语句来分离数据库表结构和实体对象之间设计.

那我们要做什么呢?

我们只需编写对应Action操作的对应的SQl 语句, MyBatis的工作则是替代我们去解决数据库表结构与实体对象之间的映射.其实这种方式在MyBatis团队内部把DataMapper直观叫做SQL Mapper.

到这里你大概明白MyBatis的底层是在做什么工作了.

到这里大概预览MyBatis底层工作原理.来进一步解析SQL Mapper的核心.MyBatis团队当初在设计这个框架.巧妙采用SQL Statument作为灵活映射载体.任何一个SQL语句都可以看做是数据库的流入和流出. 输入的值作为参数[Parameter] 通常出现And/Where条件子句中. 输出的数据则一般体现Select中指定表字段.列 举一个例子吧 一条SQL语句:

当执行一条查询语句时查询数据作为OutPut输出结果 ,条件后则作为输入参数Parameter.这种新的角度来看SQL 语句是在我们单一使用时所看不到的.一条平常SQL语句给人耳目一新感觉.这也是MyBatis在设计 一个独到匠心之处. 这又给我们带来什么呢?

作为独立中间层SQl Mapper为Developer提供足够的灵活性.而这些相对Nhibernater一站式封装不可见的底层来说.为DVP开放一个可以灵活操作的窗口.可以在不修改数据库表结构的前提下轻松地操作数据使之与对象EntityModel模型进行匹配. 同时不要忘了SQl语句本身所带来的强大语法支持.直接可以使用内置的数据库函数或存储过程来返回多个不同的表或结果. 这种直观的操作不得不说对DVP来说在很具有诱惑性.

在没有提出ORM这个概念之前.如果要做一次数据访问.MS给我们API中关联几个对象SQLConnection、SQlCommand./SQlDataReader等都是不可或缺的.以前我记得还在使用VS2005是Petshop中也能看到SQLHelper的身影.甚至每个人对SQLHelper需要都不一样.在其中添加访问数据库功能和扩展也不尽相同.

不知各位是否还记得在02年MS推出C#和.NEt层以PetShop为蓝本声称以28倍的性能优势和1/4的代码量领先于Java.遭到Java社区口水战,其实这里我要说什么呢?JAVA在数据访问如果以JDBC方式也是有一个固定重复的代码. 对于高质量 业务需求下.不同语言数据访问代码重复编写必然会降低开发人员的效率.这时代码生成器应运而生. 在一定程度上把DVP从重复数据访问工作解放出来. 随着业务需要这种解放依然不够灵活彻底.而MyBatis则完全可以替代ADO.NET.

类似利用MyBatis插入一条记录 要做什么 首先配置Insert时Action执行的SQL语句:


 
 
  1. <statements>     
  2.     <Insert id="InsertCustomer"  parameterClass="Customer">     
  3.           INSERT INTO  dbo.Customer     
  4.           ( Customer_Name ,     
  5.             Customer_Sex ,     
  6.             Customer_Age ,     
  7.             Customer_Address ,     
  8.             SignOn_Data     
  9.           )    
  10.         VALUES  ( #CustomerName# , #CustomerSex# , #CustomerAge# , #CustomerAddress#,#SignDate# )    
  11.     </Insert>    
  12. <statements> 

配置完成后执行获取到Customer数据只需简洁一句:


 
 
  1. public int InsertCustomerByTest(Customer getCustomer)     
  2.    {     
  3.        //Insert Customer     
  4.        object getresult= Mapper.Instance().Insert("InsertCustomer", getCustomer);     
  5.        return Convert.ToInt32(getresult.ToString());     
  6.    } 

这样一条Cusotmer数据成功插入.相对ADO.NET那套繁琐访问数据库过程.MyBatis这种方式你会发现代码的量显著减少 但是效果是一样的.MyiBATIS的代码要简练得多 而且也更容易维护.只需你做好SQL语句映射配置.其他相关"隐藏"资源管理工作则有MyBatis取代了.就想Batis团队Blog中一句话:"just care what do you want " 只需关注你所关心的.或是说在这套框架约束下你需要持续维护即可.类似映射关系.以极小代价换取同样的效果.

其实每一种框架都建立于规则和约束之上的.而对于低层次的框架类似ADO.NET 虽然提供灵活 完整的API使用. 却难以使用.但是我们却无法忽视这种低层次框架所适用范围. 而较高层次的框架如O/RM工具非常易用,剔除了重复代码工作量.但我们不能忘了往往这种自动化是建立更多的假设和约束之上.这也导致有些ORM框架不能完整适用更多的应用程序.这也就某种程度上照成有些ORM框架在解决一些复杂棘手问题之后同样也留下一切不可逾越的缺陷.当了解一个ORM框架原理后 也应该客观正视它所具有的优缺点.在合适场景使用才能发挥类似MyBatis ORM框架所带来高效.

so How To Use Mybatis?先了解MyBatis具有优缺点.

MyBatis框架高于ADO.NET 却没有Nhibernater一站式封装. MyBatis更多体现的是"半自动化"灵活性 这样就导致Mybatis就具有自己使用范围.

[1]不适用SQL的动态生成

MyBatis突出体现中一点就是SQL语句得开发人员自己编写. 这也是体现MyBAtis”半自动”这个核心特点. 这也是区别Nhibernater顶层对SQL动态生成一个很重要因素.但这也给MyBatis带来一定限制.

如果应用程序中设计核心SQL是动态生成的.这个时候你就发现MyBatis的表现就极为低效.MyiBATIS有着很强大的动态SQL特性,支持高级查询,甚至是一些动态的更新功能。但如果程序中的每条语句都是动态生成的,那么最好还是使用原生的ADO.NET,或者构建自己的框架。MyiBATIS的强大很大程度上体现在允许开发人员自由地手工编写SQL,直接操作SQL。如果大部分SQL都是动态生成的,那么这个优势无疑就丧失掉了

[2]提倡关系型数据库

其实昨天我还看到MyBatis官方论坛有的DVP把MyBatis使用以原始文件为基础的数据管理上 类似XML数据文件.中使用MyBatis框架.当然也社区中反馈不少使用相关问题.从官方团队反馈翻译过来:MyiBATIS不会对环境做出很多假设。但它仍然希望您使用的是一款真正的关系型数据库,同时支持事务和相对标准的SQL及存储过程。即使是一些知名的数据库也会有不支持关系型数据库关键特性的情况。MySQL的早期版本不支持事务,因此MyiBATIS用起来就不太好.官方明确在3.0提示建议使用关系型数据库.

[3]MyBatis的性能

性能这个在ORM框架也是一个很重要的因素.但是从一开始我并不对MyBatis的性能有过多的担心.毕竟把执行SQL权利交给程序员自己.这在很大程度上未性能留有余步. 其实昨天我看到IBM上对MyBatis原理类库结构大概用Refector看了一下核心的代码.其实在映射处理上采用.NEt的反射机制来实现匹配.任何框架都会存在或多或少的性能损失。一般地,比较一下手工编写的ADO.NET和MyiBATIS,在一个for循环中遍历一百万次,会发现ADO.NET更具优势。幸运的是,在当今应用程序开发中,这并不是关键的性能点。更为重要的是,如何从数据库中获取数据,何时获取它,以及获取的频率。例如,从数据库中获取分页后的列表数据能显著地提升应用程序的性能,因为这样就避免了一次加载过多的数据。类似的,使用像延迟加载[lazy load]这样的特性可以避免在给定的用例下加载不必要的数据。另一方面,如果我们确定需要加载复杂的对象属性,而这些属性来自于多个数据表,那么使用单条SQL来加载数据也可以极大地改善性能。iBATIS提供了多种性能优化策略.性能删MyBatis完全能满足大部分需求.

当然如上只是提到个人认为需要注意的地方.MyBatis本身是办ORM 但是依然具有ORM框架的提高生产力,易用,架构上支持分层的特点等.

参考资料:

深入分析IBatis框架系统架构和隐射原理

Wiki MyBatis Detail

camel.apache.org[Mybatis]

introduction-to-ibatis-mybatis-an-alternative-to-hibernate-and-jdbc



本文转自chenkaiunion 51CTO博客,原文链接:http://blog.51cto.com/chenkai/763672

相关文章
|
22天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
38 3
|
27天前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
87 3
|
1月前
|
编译器 C++ 开发者
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
10天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
25 1
|
15天前
|
数据采集 存储 编解码
一份简明的 Base64 原理解析
Base64 编码器的原理,其实很简单,花一点点时间学会它,你就又消除了一个知识盲点。
48 3
|
21天前
|
测试技术 API 开发者
精通.NET单元测试:MSTest、xUnit、NUnit全面解析
【10月更文挑战第15天】本文介绍了.NET生态系统中最流行的三种单元测试框架:MSTest、xUnit和NUnit。通过示例代码展示了每种框架的基本用法和特点,帮助开发者根据项目需求和个人偏好选择合适的测试工具。
33 3
|
1月前
|
前端开发 Java 应用服务中间件
21张图解析Tomcat运行原理与架构全貌
【10月更文挑战第2天】本文通过21张图详细解析了Tomcat的运行原理与架构。Tomcat作为Java Web开发中最流行的Web服务器之一,其架构设计精妙。文章首先介绍了Tomcat的基本组件:Connector(连接器)负责网络通信,Container(容器)处理业务逻辑。连接器内部包括EndPoint、Processor和Adapter等组件,分别处理通信、协议解析和请求封装。容器采用多级结构(Engine、Host、Context、Wrapper),并通过Mapper组件进行请求路由。文章还探讨了Tomcat的生命周期管理、启动与停止机制,并通过源码分析展示了请求处理流程。
|
1月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
47 9
|
1月前
|
开发框架 缓存 前端开发
electron-builder 解析:你了解其背后的构建原理吗?
本文首发于微信公众号“前端徐徐”,详细解析了 electron-builder 的工作原理。electron-builder 是一个专为整合前端项目与 Electron 应用的打包工具,负责管理依赖、生成配置文件及多平台构建。文章介绍了前端项目的构建流程、配置信息收集、依赖处理、asar 打包、附加资源准备、Electron 打包、代码签名、资源压缩、卸载程序生成、安装程序生成及最终安装包输出等环节。通过剖析 electron-builder 的原理,帮助开发者更好地理解和掌握跨端桌面应用的构建流程。
65 2
|
12天前
|
供应链 安全 分布式数据库
探索区块链技术:从原理到应用的全面解析
【10月更文挑战第22天】 本文旨在深入浅出地探讨区块链技术,一种近年来引起广泛关注的分布式账本技术。我们将从区块链的基本概念入手,逐步深入到其工作原理、关键技术特点以及在金融、供应链管理等多个领域的实际应用案例。通过这篇文章,读者不仅能够理解区块链技术的核心价值和潜力,还能获得关于如何评估和选择适合自己需求的区块链解决方案的实用建议。
35 0

推荐镜像

更多
下一篇
无影云桌面