目录
重点
mybatis如何防止sql注入
#和$的区别
mybatis一级缓存、二级缓存
为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别
基础
什么是MyBatis
谈谈你为什么用MyBatis,有什么优点
MyBatis有哪些缺点
如何获取自动生成的主键
属性名和字段名不一致的情况
MyBatis中用到了哪些设计模式
映射文件中处理CRUD操作的标签以外还有哪些标签?
MyBatis中的分页
使用Mapper接口的使用规范
扩展
介绍下MyBatis的工作原理
mybatis 有哪些执行器(Executor)?
谈谈你对SqlSessionFactory的理解
谈谈你对SqlSession的理解
Spring中是如何解决MySQL的SqlSession的线程安全问题的?
mybatis 是否支持延迟加载?延迟加载的原理是什么?
参考
重点
mybatis如何防止sql注入
注意:但凡是sql注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成sql语句的一部分,对于用户输入的内容或传递的参数,我们应该要时刻保持警惕,这是安全领域里的【外部数据不可信任】的原则,纵观web安全领域的各种攻击方式,大多数都是因为开发者违反了这个原则而导致的,所以自然能想到,就是变量的检测、过滤、验证下手,确保变量是开发者所预想的。
1、检查变量数据类型和格式
数据类型检查,sql执行前,要进行数据类型检查,如果是邮箱,参数就必须是邮箱的格式,如果是日期,就必须是日期格式;
只要是有固定格式的变量,在SQL语句执行前,应该严格按照固定格式去检查,确保变量是我们预想的格式,这样很大程度上可以避免SQL注入攻击。
如果上述例子中id是int型的,效果会怎样呢?无法注入,因为输入注入参数会失败。比如上述中的name字段,我们应该在用户注册的时候,就确定一个用户名规则,比如5-20个字符,只能由大小写字母、数字以及汉字组成,不包含特殊字符。此时我们应该有一个函数来完成统一的用户名检查。不过,仍然有很多场景并不能用到这个方法,比如写博客,评论系统,弹幕系统,必须允许用户可以提交任意形式的字符才行,否则用户体验感太差了。
2、过滤特殊符号
3、绑定变量,使用预编译语句
#和$的区别
mybatis一级缓存、二级缓存
1、一级缓存:在同一个SqlSession中,当我们执行查询以后,查询的结果会同时存入sqlSession中,再次查询的时候,先去sqlSession中查询,有的话直接拿出,当sqlSession消失时,mybatis的一级缓存也就消失了,当调用sqlSession的修改、添加、删除、commit()、close()等方法时,会清空一级缓存。
一级缓存的作用域是SqlSession级别的,只对当前SqlSession有效。
2、二级缓存:指的是mybatis中的sqlSessionFactory对象的缓存,由同一个sqlSessionFactory对象创建的sqlSession共享其缓存,但是其中缓存的是数据而不是对象。当命中二级缓存时,通过存储的数据构造成对象返回。查询数据的时候,查询的流程是二级缓存 > 一级缓存 > 数据库。
3、如果开启了二级缓存,sqlSession进行close()后,才会把sqlSession一级缓存中的数据添加到二级缓存中,为了将缓存数据取出执行反序列化,还需要将要缓存的pojo实现Serializable接口,因为二级缓存数据存储介质多种多样,不一定只存在内存中,也可能存在硬盘中。
为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别
Mybatis 被称为半自动 ORM 映射工具,主要原因在于它在对象关系映射和数据库交互过程中结合了手动控制和自动化辅助的特点。具体来说,Mybatis 的“半自动”特性体现在以下几个方面:
手动编写 SQL:Mybatis 要求开发者手动编写 SQL 语句,包括查询、插入、更新和删除等操作。这给予了开发者对 SQL 查询的高度控制权,可以根据实际需求优化 SQL,但同时也意味着需要手动维护这些 SQL 语句。
SQL 映射定义:虽然 Mybatis 提供了映射 XML 文件来定义 Java 对象与数据库表之间的映射关系,减少了直接处理 JDBC 代码的繁琐,但是关联对象或集合的查询仍然需要通过手动编写的 SQL 来完成,而不是像全自动 ORM 工具那样自动生成。
结果集映射:Mybatis 支持自动将查询结果映射到 Java 对象,但映射规则需要手动定义。开发者需要在映射文件中指定哪些列映射到对象的哪些属性。
与之相对的是全自动 ORM 映射工具,如 Hibernate,它们的特点包括:
自动生成 SQL:Hibernate 可以根据实体类和映射关系自动生成 SQL 语句,大大减少了手动编写 SQL 的工作量。
对象导航查询:Hibernate 支持通过对象关系直接进行关联对象或集合的查询,而无需编写额外的 SQL,提高了开发效率。
更深层次的自动化:Hibernate 提供了更多的自动化管理功能,比如事务管理、缓存策略、懒加载等,这些特性让开发者可以更专注于业务逻辑而非底层数据访问细节。
因此,Mybatis 与全自动 ORM 工具的主要区别在于控制与自动化的平衡点:Mybatis 强调手动控制 SQL 和映射细节,适合需要高度定制化和性能优化的场景;而全自动 ORM 工具如 Hibernate 则倾向于提供全面的自动化解决方案,更适合快速开发和对数据库操作透明度有较高要求的项目。
基础
什么是MyBatis
MyBatis是一个基于Java的持久层框架,用于简化数据库操作,特别是在Java Web应用中。
谈谈你为什么用MyBatis,有什么优点
MyBatis有哪些缺点
如何获取自动生成的主键
在使用insert标签的时候,usegeneratedKeys=true keyproprety='id'
属性名和字段名不一致的情况
MyBatis中用到了哪些设计模式
映射文件中处理CRUD操作的标签以外还有哪些标签?
MyBatis中的分页
使用Mapper接口的使用规范
扩展
介绍下MyBatis的工作原理
Mybatis 框架在工作时大致经过8个步骤,如下:
1、读取 Mybatis 配置文件 mybatis-config.xml,该配置文件作为 Mybatis 的全局配置文件,配置了 Mybatis 的运行环境和数据库连接等信息。
2、加载映射文件 mapper.xml,该文件中配置了操作数据库的 sql 语句,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml 可以加载多个配置文件,每个配置文件对应数据库中的一张表。
3、通过 SqlSessionFactoryBuilder 对象的 build() 方法构建会话工厂,且 build() 方法参数为 mybatis-config.xml 配置文件的输入流,通过 Mybatis 的环境等配置信息构建会话工厂 SqlSessionFactory - 工厂设计模式。
4、创建 SqlSession 对象,由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 的所有方法。
5、Mybatis 的底层定义了一个 Executor 接口来操作数据库,它会根据 SqlSession 传递的参数动态的生成需要执行的 SQL 语句,同时负责查询缓存的维护。
6、在 Executor 接口的方法中,包含一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等。Mapper.xml 文件中的一个SQL对应一个 MappedStatement 对象,SQL 的 id 即是 MappedStatement 的 id。
7、输入映射参数,在执行方法时 MappedStatement 对象会对用户执行 SQL 语句的输入参数进行定义(可以定义为 Map、List 类型、基本类型和 POJO 类型),Executor 执行器会通过 MappedStatement 对象在执行 SQL 前,将输入的 java 对象映射到 SQL 语句中。这里对输入参数的映射过程就类似于 JDBC 编程中对 preparedStatement 对象设置参数的过程。
8、输出结果映射,在数据库中执行完SQL语句后 MappedStatement 对象会对 SQL 执行输出的结果进行定义(可以定义为 Map、List 类型、基本类型、POJO类型),Executor 执行器会通过 MappedStatement 对象在执行 SQL 语句后,将输出结果映射到 java 对象中。这种将输出结果映射到 java 对象的过程就类似于 JDBC 编程中对结果的解析处理过程。
参考:MyBatis 的工作原理解析_mybatis原理-CSDN博客
mybatis 有哪些执行器(Executor)?
1、mybatis有三种基本的Executor执行器:
(1)、SimpleExecutor(简单执行器)
MyBatis的默认执行器类型。每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
(2)、ReuseExecutor(重用执行器)
执行update或select,以sql做为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而且放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。
(3)、BatchExecutor(批处理执行器)
执行update,将所有sql通过addBatch()都添加到批处理中,等待统一执行executeBatch(),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
2、作用范围:
Executor的这些特点,都严格限制在SqlSession生命周期范围内。
3、Mybatis中如何指定使用哪一种Executor执行器?
在mybatis的配置文件中,可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数。
谈谈你对SqlSessionFactory的理解
SqlSessionFactory是MyBatis中的一个关键接口,用于创建SqlSession对象,是MyBatis的核心组件之一。
SqlSessionFactory是通过SqlSessionFactoryBuilder创建的,SqlSessionFactoryBuilder会读取MyBatis的配置文件(mybatis-config.xml),并根据配置文件中的信息构建SqlSessionFactory对象。
SqlSessionFactory的主要作用是提供了创建SqlSession对象的方法,SqlSession对象是MyBatis中执行数据库操作的主要接口。SqlSession可以通过SqlSessionFactory的openSession方法创建,并且可以设置是否自动提交事务。SqlSession的生命周期应该在一个较小的范围内控制,避免长时间持有,以免占用数据库连接资源。
SqlSessionFactory可以被多个线程共享,应该保证SqlSessionFactory的单例,避免资源浪费。
除此之外,SqlSessionFactory还可以配置MyBatis的一些全局属性,如数据库连接池、缓存等,这些全局属性可以在整个应用程序中共享,从而提高应用程序的性能和可维护性。
总之,SqlSessionFactory是MyBatis中非常重要的一个接口,负责创建SqlSession对象和管理MyBatis全局属性的配置,使用SqlSessionFactory可以简化数据库操作的编写和管理,提高应用程序的性能和可维护性。
谈谈你对SqlSession的理解
MyBatis是一个优秀的持久层框架,而SqlSession则是MyBatis框架中最为核心的组件之一。SqlSession可以看做是对数据库操作的一次会话,每个会话中可以执行多次数据库操作。下面是对SqlSession的一些理解:
SqlSession的生命周期:SqlSession的生命周期是从它的创建到关闭。SqlSession的创建可以通过SqlSessionFactory来创建,一般情况下,我们在需要访问数据库的时候,就会创建一个SqlSession对象。当SqlSession对象不再使用时,应该将其关闭。
SqlSession的作用:SqlSession封装了对数据库的操作,包括数据的插入、更新、删除和查询等操作。通过SqlSession可以执行Mapper中定义的方法,并将执行结果返回给应用程序。SqlSession还提供了事务管理的支持。
SqlSession的管理:在MyBatis中,SqlSession的管理是由SqlSessionFactory来管理的。SqlSessionFactory可以通过配置文件或者Java代码来创建,每个应用程序通常只需要一个SqlSessionFactory实例,用于创建SqlSession对象。在应用程序中,SqlSession的管理一般由Spring框架或者自己手动管理。
SqlSession的线程安全性:SqlSession不是线程安全的,每个SqlSession实例都应该被单独使用,不能被多个线程共享。在多线程环境下,如果多个线程共用一个SqlSession对象,则可能会出现数据混乱的情况,因此需要保证每个线程都有自己的SqlSession实例。
总之,SqlSession是MyBatis框架中最为核心的组件之一,它封装了对数据库的操作,提供了事务管理的支持,并由SqlSessionFactory进行管理。使用SqlSession时需要注意其生命周期、线程安全性等问题。
Spring中是如何解决MySQL的SqlSession的线程安全问题的?
Spring提供了两种解决方案来解决SqlSession的线程安全问题:
1.使用SqlSessionTemplate
SqlSessionTemplate是Spring提供的一个线程安全的SqlSession实现。它封装了SqlSession的操作,并确保每个线程都有自己的SqlSession实例。因此,在多线程环境下,每个线程都可以独立地使用自己的SqlSession实例,而不会相互干扰。可以在配置文件中定义SqlSessionTemplate bean,然后在需要使用SqlSession时注入该bean。
2.使用@Scope注解
另一个解决方案是在配置文件中使用@Scope注解,将SqlSession的作用域设置为prototype。这将确保每次从容器中获取SqlSession时都会返回一个新的实例,因此每个线程都可以使用自己的SqlSession实例。可以在配置文件中声明SqlSession bean,并使用@Scope注解将其作用域设置为prototype。在需要使用SqlSession时,可以注入该bean。
mybatis 是否支持延迟加载?延迟加载的原理是什么?
1、mybatis 是否支持延迟加载?
支持延迟加载。
MyBatis通过在映射文件中配置lazyLoadingEnabled属性来开启延迟加载。
2、延迟加载的原理是什么?
原理是当查询对象时,只加载对象的基本属性,而对于延迟加载的关联对象,只在真正需要使用时,通过创建代理对象,再次向数据库查询加载其数据。
比如调用a.getB().getName(),拦截器方法invoke()发现a.getB()为null,会单独发送事先准备好的查询关联B对象的sql语句,把B查询出来然后调用a.setB(b),也是a的对象的属性b就有值了,然后调用getName(),这就是延迟加载的原理。
参考
MyBatis源码面试题_sqlsession的生命周期-CSDN博客