谈谈MyBatis持久层框架
谈谈 MyBatis
源自官方文档:MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java 对象为数据库中的记录。一句话就是对 JDBC 的封装。
MyBatis 的优缺点
优点:
1:SQL 语句与 Java 代码分离,便于统一管理。
2:提供 xml 标签,支持动态 SQL 编写。
3:消除了 JDBC 中大量冗余的代码,并通过数据库连接池维护连接。
4:很好的与各种数据库兼容,能够与 Spring 很好的集成。
5:提供对象关系映射标签,支持对象与数据库的 ORM 字段关系映射。
缺点:
1:SQL 语句编写的工作量较大,尤其是字段多,关联查询复杂时对于 SQL 的基础功底有一定要求。
2:对性能要求较高,需求变化较多的项目适合使用 MyBatis。
什么是 ORM
对象关系映射(Object Relational Mapping,简称 ORM),描述实体类属性和数据库字段之间的映射关系,将面向对象语言程序中的对象自动持久化到关系型数据库中,场景的 ORM 框架:Hibernate、MyBatis 等。
半自动和全自动 ORM 映射工具
Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或关联集合对象时,可以根据对象关系模型直接获取。
MyBatis 属于半自动 ORM 映射工具,使用 MyBatis 查询关联对象或关联集合对象时,需要手动编写 SQL 来完成。
JDBC 的不足和 MyBatis 的解决
1:JDBC 数据库创建链接和释放资源频繁造成系统资源浪费从而影响系统性能。MyBatis 使用数据库连接池管理数据库连接。
2:JDBC 的 SQL 语句写在代码中造成代码不易维护。MyBatis 将 SQL 语句配置在 mapper.xml 文件中与 Java 代码进行分离。
3:JDBC 的 SQL 语句传参非常麻烦,where 条件不确定且占位符要与参数一意对应。MyBatis 自动将 Java 对象映射到 SQL 语句中。
4:JDBC 对结果集解析较为麻烦,SQL 语句变化导致解析代码变化且解析前需要遍历。MyBatis 自动将 Java 对象映射到 SQL 语句中。
MyBatis 的编码步骤
1:创建 SqlSessionFactory。
2:通过 SqlSessionFactory 创建 SqlSession。
3:通过 SqlSession 执行数据库操作。
4:调用 session.commit() 提交事务。
5:调用 session.close() 关闭会话。
MyBatis 中 #{} 和 ${} 的区别
${} 是 properties 文件中的变量占位符。用于标签属性值和 SQL 内部的静态文本替换。
#{} 是 SQL 语句参数的占位符。MyBatis 会将 SQL 语句中的 #{} 替换为 ? 号。
#{} 方式能很大程度上防止 SQL 注入,一般使用 #{} 而不使用 ${}。${} 无法防止SQL 注入,一般用于传入数据库对象,比如表名。
什么是 SQL 注入
源自百度百科:SQL 注入即是指 web 应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在 web 应用程序中事先定义好的查询语句的结尾上添加额外的 SQL 语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。一句话就是通过拼接非法的可执行的 SQL 语句非法获取数据信息。
MyBatis 的 mapper 接口调用的要求
1:mapper 接口的类路径即是 mapper.xml 文件中的 namespace 属性值。
2:mapper 接口方法名和 mapper.xml 文件中定义的每个 SQL 的 id 相同。
3:mapper 接口方法的入参类型和 mapper.xml 文件中定义的每个 SQL 的 parameterType 的类型相同。
4:mapper 接口方法的返回值类型和 mapper.xml 文件中定义的每个 SQL 的 resultType 的类型相同。
MyBatis 中的一级缓存与二级缓存
一级缓存:基于 PerpetuaCache 的 HashMap 本地缓存,作用域为 Session。当 Session flush 或 close 后,该 Session 中的所有 Cache 就将被清空。
二级缓存:与一级缓存机制相同,也是基于 PerpetuaCache 的 HashMap 本地缓存,但其作用域为 namespaces。二级缓存可以自定义存储源,例如 Ehcache。二级缓存会对一个 namespace 对应的 mapper.xml 文件中所有的 select 操作结果都进行缓存,不同线程之间就可以共用二级缓存。
当某一个作用域,不管是一级缓存 Session 还是二级缓存 namespaces 进行了增删改操作,默认该作用域下所有 select 中的缓存将被清除。
二级缓存开启:MyBatis 配置文件中开启 <cache />。
二级缓存的策略:<cache readOnly="true"/> 二级缓存返回给所有调用者是同一个缓存对象实例,调用者更新缓存实例后可以会造成其他调用者调用时出现数据不一致的情况。<cache readOnly="false"/> 二级缓存返回给所有调用者是总缓存对象的拷贝,不同调用者获取的是缓存对象的不同实例,各自维护各自的缓存对象,更新不会影响到其他的调用者。二级缓存默认使用安全的 <cache readOnly="false"/> 策略。
xml 文件中,除了常见的 CRUD 标签外还有哪些标签
其他 5 个标签 resultMap / parameterMap / sql / include / selectKey。
动态 SQL 的 9 个标签:trim / where / set / foreach / if / choose / when / otherwise / bind。
mapper 接口的实现原理
mapper 接口的底层是通过 Map<String, MapperedStatement> 集合维护。key 为接口的路径名 + 方法名拼接的字符串或 namespace + id,value 为 MapperedStatement 对象。MapperedStatement 对象即为 namespace 下的标签 id 对应的对象,例如 namespace=”com.xpy.mapper.UserMapper” 下的 select / insert / update / delete 标签 id=”getUserById” 对应的对象。接口的路径名 + 方法名拼接的字符串,例如 com.xpy.mapper.UserMapper.getUserById 定位一个唯一的 MapperedStatement 对象。
MapperedStatement 对象唯一说明 mapper 接口中的的方法不能重载。
不同的 xml 文件中,如果配置了 namespace,id 就可以重复,如果没有配置 namespace,则 id 对应的数据就会造成覆盖。
mapper 接口的工作原理是 JDK 动态代理。MyBatis 运行时会使用 JDK 动态代理为 mapper 接口生成代理对象 proxy,代理对象 proxy 会拦截接口方法转而去执行 MapperedStatement 对象,并将 SQL 的执行结果返回。
MyBatis 分页和分页插件的原理
MyBatis 使用 RowBounds 对象进行分类,是针对 ResultSet 结果集执行的内存分页。要实现物理分页可以通过 SQL 中配置 LIMIT 参数或使用分页插件。
分页插件的原理是使用 MyBatis 提供的插件接口实现自定义插件,在插件的拦截方法内拦截待执行的 SQL 语句进行重写,根据 dialect 方言添加对应的物理分页语句和参数。
MyBatis 的插件运行原理
MyBatis 仅支持 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这四种接口的插件。每当执行这四种接口对象的方法时,就会进入拦截方法,也就是 InvocationHandler 的 invoke 方法,拦截指定需要拦截的方法。
编写一个插件只需实现 MyBatis 的 Interceptor 接口并重写 intercept 方法,然后在给插件编写一个注解,指定要拦截哪一个接口的哪些方法,最后在配置文件中配置编写的插件。
MyBatis 如何将 SQL 执行结果封装为目标对象返回的
第一种是通过 resultMap 标签逐一定义数据库字段名和实体类属性名之间的映射关系,第二种是使用别名,将数据库字段名写成实体类属性名,例如 t_title as title。有了映射关系后,MyBatis 会通过反射创建对象,同时给对象的属性逐一赋值并返回,找不到或没有映射关系的属性无法完成赋值。
MyBatis 的动态 SQL 的执行原理
动态 SQL 是指可以在 xml 文件中可以通过标签的形式动态编写 SQL,完成逻辑判断和动态拼接 SQL 语句的功能。动态 SQL 的执行原理是使用 OGNL 从 SQL 参数对象中计算表达式的指,根据表达式的值动态拼接 SQL。
MyBatis 关联查询的实现方式及区别
MyBatis 支持一对一、一对多、多对一、多对多的关联查询。关联对象查询有两种实现方式,第一种是单独发送一个 SQL 语句去查询关联对象,赋值给主对象并返回主对象。第二种是使用嵌套查询,使用 join 查询,一部分列是 A 对象的属性值,一部分列是 B 对象的属性值,只发送一个 SQL 语句就可以把主对象和其关联对象全都查出来。
MyBatis 的 Executor 执行器
MyBatis 有三种基本的 Executor 执行器:SimpleExecutor、ReuseExecutor、BatchExecutor。这些执行器都严格限制在 SqlSession 生命周期范围内。
SimpleExecutor:每执行一次 update 或 select,就开启一个 Statement 对象,用完立刻关闭。
ReuseExecutor:执行 update 或 select 时,以 SQL 作为 key 查找 Statement 对象,存在就使用,不存在就创建,用完后不关闭,而是放到 Map<String, Statement> 中,供下一次使用。
BatchExecutor:在执行 update 时将所有 SQL 都添加到批处理中,等待统一执行,执行器缓存了多个 Statement 对象,每个 Statement 对象都是 addBatch 完毕后,等待逐一执行 executeBatch。JDBC 批处理不支持 select。
MyBatis 配置文件中可以指定默认的 ExecutorType 执行器类型,也可以手动给 DefaultSqlSessionFactory创建 SqlSession 的方法传递 ExecutorType 参数类型。
MyBatis 是否可以映射 Enum 枚举类
可以,MyBatis 可以映射任何对象到表的列上。映射方式为自定义一个 TypeHandler,实现 TypeHandler 的 setParameter 和 getResult 方法,setParameter 方法实现 javaType 到 jdbcType 的转换,设置 SQL 占位符参数。getResult 方法实现 jdbcType 到 javaType 的转换,获取列查询结果。
MyBatis 解析标签规则
MyBatis 解析 xml 文件是按照顺序解析的,但 MyBatis 解析标签时如果发现引用了另外一个标签,但另外一个标签尚未解析到,此时就会将此标签标记为未解析状态,继续解析余下的标签,待所有标签解析完毕,MyBatis 会重新解析被标记为未解析状态的标签,此时另一个标签已经存在,也就正常解析完成了。所以如果一个标签通过 include 引用了另外一个标签的内容,则另外一个标签可以定义在任何地方。
谈谈MyBatis持久层框架的更多相关文章
- MyBatis持久层框架使用总结 转载
MyBatis持久层框架使用总结 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google co ...
- MyBatis持久层框架使用总结
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis . 2 ...
- Spring集成MyBatis持久层框架
一.MyBatis介绍 MyBatis 是一款优秀的持久层框架,它支持定制化SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的JDBC代码和手动设置参数以及获取结果集,可以使用简单的XML ...
- MyBatis持久层框架学习之01 MyBatis的起源和发展
一.MyBatis的简介 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架. MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集. MyB ...
- spring-boot+mybatis开发实战:如何在spring-boot中使用myabtis持久层框架
前言: 本项目基于maven构建,使用mybatis-spring-boot作为spring-boot项目的持久层框架 spring-boot中使用mybatis持久层框架与原spring项目使用方式 ...
- java持久层框架mybatis如何防止sql注入
看到一篇很好的文章:http://www.jfox.info/ava-persistence-framework-mybatis-how-to-prevent-sql-injection sql注入大 ...
- 持久层框架之MyBatis
1.mybatis框架介绍: MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并 ...
- Java数据持久层框架 MyBatis之背景知识三
摘录自:http://www.cnblogs.com/lcngu/p/5437281.html 对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.or ...
- Java数据持久层框架 MyBatis之API学习一(简介)
对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...
- Java数据持久层框架 MyBatis之背景知识二
对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...
随机推荐
- mysql存储过程实战
今天科比离去,今天肺炎病毒持续肆虐... 意识到生命的脆弱,今天我继续前行,比以往更加坚定和紧迫,这辈子不活好自己就算白来一趟. 最近需要用到mysql存储过程去处理一些表数据,然后利用java po ...
- kafka学习笔记01-kafka简介和架构介绍
一.kafka介绍 kafka 最开始是 Linkedin 用来处理海量的日志信息,后来 linkedin 于 2010 年贡献给了 Apache 基金会并成为了顶级项目. 后来开发 kafka 的一 ...
- 【Android 逆向】【攻防世界】黑客精神
1. apk 安装到手机,提示输入注册码 2. jadx打开apk MainActivity.java @Override // android.app.Activity public void on ...
- 如何避免Git合并远程分支时出现可读性差的日志
问题及现象 当某一分支(假设为main)的本地仓库和远程仓库都基于同一个提交进行了修改,并分别创建了新的提交时,在本地执行git push origin main会提示先要执行git pull合并远程 ...
- window上使用Putty通过ssh远程连接并通过Xming实现X11图形界面功能
# 0.先确认远程服务器的ssh配置 >>> grep X11 /etc/ssh/sshd_config X11Forwarding yes #X11DisplayOffset 10 ...
- 【ACM专项练习#03】打印图形、栈的合法性、链表操作、dp实例
运营商活动 题目描述 小明每天的话费是1元,运营商做活动,手机每充值K元就可以获赠1元,一开始小明充值M元,问最多可以用多少天? 注意赠送的话费也可以参与到奖励规则中 输入 输入包括多个测试实例.每个 ...
- 详解SSL证书系列(3)如何选择SSL证书
我们知道了在网站部署 SSL 证书后,不管是对网站本身还是对网站的用户都能够带来许多好处.那么随着 HTTPS的普及,市面上也出现了各种不同的 SSL 证书.并且由于 SSL 证书的多样性,很多人对于 ...
- 【Azure 应用服务】Azure Function 部署槽交换时,一不小心把预生产槽上的配置参数交换到生产槽上,引发生产错误
问题描述 部署Function代码先到预生产槽中,进行测试后通过交换方式,把预生产槽中的代码交换到生产槽上,因为在预生产槽中的设置参数值与生产槽有不同,但是在交换的时候,没有仔细检查.导致在交换的时候 ...
- nebula-br local-store 模式,快速搭建主备集群实践
因为线上图数据库目前为单集群,数据量比较大,有以下缺点: 单点风险,一旦集群崩溃或者因为某些查询拖垮整个集群,就会导致所有图操作受影响 很多优化类但会影响读写的操作不好执行,比如:compact.ba ...
- 用图机器学习探索 A 股个股相关性变化
在本系列的前文 [1,2]中,我们介绍了如何使用 Python 语言图分析库 NetworkX [3] + Nebula Graph [4] 来进行<权力的游戏>中人物关系图谱分析. 在本 ...