数据持久化是什么
数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。
数据模型可以是任何数据结构或对象的模型、XML、二进制流等。 当我们编写应用程序操作数据库,对表数据进行增删改查的操作的时候就是数据持久化的操作。
ORM是什么
ORM(Object/Relational Mapping)即对象关系映射,是一种数据持久化技术。它在对象模型和关系型数据库直接建立起对应关系,并且提供一种机制,通过JavaBean对象去操作数据库表的数据。
MyBatis通过简单的XML或者注解的方式进行配置和原始映射,将实体类和SQL语句之间建立映射关系,是一种半自动(之所以说是半自动,因为我们要自己写SQL)的ORM实现。
Mybatis是什么
- MyBatis框架是一个开源的数据持久层框架。
- 它的内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数的手工设置以及结果集的检索。
- MyBatis作为持久层框架,其主要思想是将程序中的大量SQL语句剥离出来,配置在配置文件当中,实现SQL的灵活配置。
- 这样做的好处是将SQL与程序代码分离,可以在不修改代码的情况下,直接在配置文件当中修改SQL。
MyBatis底层技术主要包括以下几个方面:
- JDBC:JDBC是Java语言中用于访问关系型数据库的API,MyBatis框架基于JDBC技术来实现与数据库的交互。MyBatis使用JDBC来执行SQL语句和处理结果集,同时还通过JDBC提供了事务管理支持。
- SQL解析:MyBatis使用OGNL表达式语言进行SQL解析。在XML中配置的SQL语句会被解析成一个可执行的SQL对象。该SQL对象中存储了SQL语句的各种信息(例如参数、返回值等),以及与之对应的Java类和属性信息。
- 映射器:MyBatis使用映射器(Mapper)来定义SQL语句与Java类之间的映射关系。映射器中定义了方法与SQL语句之间的对应关系,以及方法的返回值类型等信息。MyBatis可以通过注解或XML文件来定义映射器。
- 缓存:MyBatis提供了强大的缓存机制,缓存可以大幅提高系统性能。MyBatis支持一级缓存和二级缓存。一级缓存指的是SqlSession级别的缓存,二级缓存指的是Mapper级别的缓存。
- 插件机制:MyBatis提供了插件机制,可以在框架的运行过程中对SQL语句进行拦截和修改。开发人员可以通过插件机制拓展MyBatis的功能,提高框架的灵活性和可扩展性。
MyBatis框架的优缺点及其适用的场合
优点
- 与JDBC相比,减少了50%以上的代码量。
- MyBatis是易学的持久层框架,小巧并且简单易学。
- MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML文件里,从程序代码中彻底分离,降低耦合度,便于统一的管理和优化,并可重用。
- 提供XML标签,支持编写动态的SQL,满足不同的业务需求。
- 提供映射标签,支持对象与数据库的ORM字段关系映射。
缺点
- SQL语句的编写工作量较大,对开发人员编写SQL的能力有一定的要求。
- SQL语句依赖于数据库,导致数据库不具有好的移植性,不可以随便更换数据库。
适用场景
MyBatis专注于SQL自身,是一个足够灵活的DAO层解决方案。对性能的要求很高,或者需求变化较多的项目,例如Web项目,那么MyBatis是不二的选择。
MyBatis与Hibernate有哪些不同
- Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。
- Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高
- Hibernate数据库移植性远大于Mybatis,Mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。
- Hibernate对象/关系映射能力强,数据库无关性好,可以节省很多代码,但是使用难度比Mybatis高
Mybatis缓存了解吗
mybatis有二级缓存的,其中一级缓存默认开启,二级缓存需要手动配置开启,
一级缓存
- 一级缓存是默认开启的;
- 底层其实是基于hashmap的本地内存缓存;
- 作用域是session(其实就相当于一个方法);
- 当session关闭或者刷新的时候缓存清空;
- 不同sqlsession之间缓存互不影响;
一级缓存有数据一致性问题:
比如:有两个更新操作对同一条数据
如果是sqlsessionA进行了更新操作,则sqlsessionA对应的一级缓存被清空;
如果是sqlsessionB进行了更新操作,则此更新操作对改sqlsessionA不可见;
那么其实这个时候sqlsessionA再查的数据就是过期失效数据了;
建议:
- 单个sqlsession的生命周期不能过长;
- 如果是对同一个语句更新尽量使用同一个sql,也就是同一个sqlsession;
- 建议关闭一级缓存,
二级缓存
- 二级缓存需要我们手动开启,它是mapper级别的缓存;
- 也是基于HashMap存储
- 作用范围是同一个 namespace 下的mapper 映射文件内容。
- 多个 SqlSession 之间可以共享缓存内容
如果对某一个表的操作查询可能有多个namespace,那么得到的数据就是有问题的;
建议关闭mybatis的一级缓存和二级缓存
#{}和${}的区别是什么?
#{}
是预编译处理,${}
是字符串替换。- Mybatis在处理
#{}
时,会将sql中的#{}
替换为?号,调用PreparedStatement的set方法来赋值; - Mybatis在处理
${}
时,就是把${}
替换成变量的值。 - 使用
#{}
可以有效的防止SQL注入,提高系统安全性。#{}是经过预编译的,是安全的;${}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。
mybatis是如何做到防止sql注入的
SQL注入是一种常见的攻击方式。攻击者在界面的表单信息或URL上输入一些奇怪的SQL片段(例如“or ‘1’=’1’”这样的语句),有可能入侵参数检验不足的应用程序。
MyBatis 通过参数绑定和预编译语句两个方面来防止 SQL 注入。
- 参数绑定:使用
#{}
语法来表示参数占位符“?”。这样可以确保参数值会被正确地转义和处理。避免了直接将参数值拼接到 SQL 语句中的情况。 - 预编译语句:预编译语句是一种将 SQL 语句分成两步执行的机制,首先将 SQL 语句发送给数据库进行编译,然后再将参数值传递给编译后的语句执行。参数值会以参数的形式传递给数据库,而不是直接拼接到 SQL 语句中。
SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。
实体类的属性名和表的字段名不一样怎么办
- 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
- 使用 @Results 和 @Result 注解来配置映射关系。
- 在 SQL XML映射文件中通过 < resultMap > 和 < result > 标签来配置映射关系。
Dao接口的工作原理是什么
Dao接口即Mapper接口。
接口的全限名,就是映射文件中的namespace的值;
接口的方法名,就是映射文件中Mapper的Statement的id值;
接口方法内的参数,就是传递给sql的参数。
Mapper 接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,转而执行MapperStatement所代表的sql,然后将sql执行结果返回。
Dao接口里的方法,参数不同时,方法能重载吗
Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MapperStatement。Mapper接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻找策略。