MyBatis
MyBatis
ORM框架
什么是ORM?
Object Relation Manager对象关系映射,负责对象类型与数据库类型之间的映射处理
MyBatis 与 Hibernate的区别
Mybatis
- 半自动映射框架
- Sql需要自己编写,映射关系需要自己配置
Hibernate
- 全自动映射框架
- Sql需要自己写,映射关系需要自己配置
为什么要使用Mybatis?
- Hibernate虽然封装了Sql,简化了开发,但是不能优化sql,如果我们想写一个高级的sql,需要去学HQL语言(Hibernate的操控数据库的语言),增加了开发难度
- Hibernate还是一个全映射框架,假如你只需要查一个字段,他也会查出所有的字段,全部返回给你
MyBatis工作原理
重要
读取全局配置文件 - MyBatis-config.xml
加载映射文件 - xxxMapper.xml
构造会话工厂 - SqlSessionFactory 负责生成SqlSession对象
创建会话对象 - 由SqlSessionFactory创建SqlSession对象,该对象中包含了执行SQL语句的所有方法
Executor 执行器
MyBatis定义了一个Executor接口操作数据库,根据SqlSession传递的参数动态地生成需要执行的Sql语句,同时负责查询缓存的维护
MappedStatement对象
在
Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息输入参数映射
输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对
preparedStatement对象设置参数的过程输出参数映射
输出结果类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程
全局配置文件
根元素configuration
properties
加载Properties外部文件配置
settings
配置Mybatis运行时的行为
- CacheEnabled 配置二级缓存是否开启
- lazyLoading 配置是否可以延迟加载
- useColumnLable 使用列标签代替列名
- defaultStatemntTimeOut 默认的会话等待时间
- mapUnderscoreToCamelCase 下划线转为驼峰
typeAliases
- 设置别名
- 别名部分大小写
- 也能用注解@Alias
typeHandlers
处理对象与数据库数据类型之间的映射关系
ObjectFactory
对象工厂
Plugins
载入插件,比如拦截调用的一些插件
environments
- 配置数据源
- UNPOOLED 不使用池
- POOLED 使用池
- JNDI
- 配置事务
- 使用Spring事务管理,所以这里不需要管
databaseIdProvider
用来配置不通的数据库
mappers
配置映射文件所在的位置
映射文件
mapper.xml文件
- insert
- id
- parameterType 可以省略
- 返回值默认有三种integer、long、boolean
- update 同上
- delete 同上
- select
- resultType
- 配置返回数据的类型
- resultType=”map” 返回一个key为列名,value为值的一个map对象
- resultType
参数处理
- 对于单个参数,不做特殊处理,直接返回结果
- 对于多个参数,需要用@Param配置名称,如果不使用注解,那么需要使用param1、param2来获取
- 如果参数很多,和POJO的类型一样,那么直接传POJO即可
- 如果很多,也不常用,也可以传Map
- 如果很多,经常使用,可以编写TO类
#{}与${}的区别
#{}相当于preStatement调用,可以避免Sql注入
preparestatement在程序第一次查询数据库之前sql语句就被数据库进行了分析、编译、优化以及具体的查询计划也都形成了,之后参数进来的时候不会被分析处理为指令简单来说就是:不让参数参与编译阶段,而是使用占位符代替,从而解决了sql注入问题
${}可以用在一些不能使用#{}的时候,比如排序
resultmap实现高级映射
- association
- 实现分步查询
- 用在一对一关系
- 在此基础上可以实现延迟加载 即只有用到了才会执行这个Sql
- collection
- 实现一对多关系映射
- 也可以实现延迟加载
- 使用ofType属性配置集合中元素的类型
缓存
缓存的本质,就是一个map对象
Mybatis有两级缓存
一级缓存
- 属于SqlSession级别的缓存,同一次数据库会话使用同一个SqlSession
- 失效的情况,有四种
- 使用两个不同的SqlSession
- 使用相同的SqlSession
- 查询条件不同
- 清除了缓存
- 在两次查询期间执行了增删改操作
二级缓存
- 属于namespace级别的缓存,即一个mapper文件对应一个二级缓存(比如学生Mapper一个、专业Mapper一个等等)
- 当sqlSession提交或者关闭后,它的数据就会存放在二级缓存中
查询顺序
先查二级缓存,再查一级缓存,如果一二级缓存都没有命中,查数据库
二级缓存配置cache
eviction配置回收策略
- LRU默认
- FIFO
- SOFT 回收软引用
- WEAK 回收弱引用
readOnly
- true mybatis认为你不会做修改操作,然后每次都会直接返回缓存中的值
- false (默认) mybatis认为你会做修改,所以每次返回都是返回缓存中反序列化克隆后的结果
flushInterval
配置多久时间清空一次缓存,默认不清空
type
我们可以自己实现缓存,实现接口cache,然后将实现类的全限定类名作为type的值即可
#{}和${}
#{}是预编译处理,是占位符,${}是字符串替换,是拼接符
- Mybatis处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement来赋值
- Mybatis在处理${}时,就是把${}替换成变量的值Statement来赋值
- #{}的变量替换是在DBMS中,变量替换后,#{}对应的变量自动加上单引号
- ${}的变量替换是在DBMS外,变量替换后,${}对应的变量不会加上单引号
- 使用#{}可以有效的防止SQL注入,提高系统安全性
- 占位符会将输入的值视为参数数据而不是SQL代码
- 拼接符会当做SQL代码,如果被恶意注入比如输入SELECT * FROM users WHERE username = ‘admin’; DROP TABLE users; *–’;,这里的- -*是SQL语句的注释符号,会导致后面的内容被忽略