MyBatis特性
- MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架
- MyBatis避免了几乎所有的JDBC代码和手动参数设置
- Mybatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java和POJO(Plan Old Java Object,普通的Java对象)映射成数据库中的记录
- MyBatis是一个半自动的ORM(Object Relation Mapping)框架
MyBatis和其他持久化层技术的比较
-
Hibernate 和 JPA
- 程序中长难复杂的SQL需要绕过框架
- 内部自动生产的SQL,不容易做特殊优化
- 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难
- 反射操作太多,导致数据库性能下降
-
MyBatis
- 轻量级、性能出色
- SQL和Java编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据、
- 开发效率稍逊于Hibernate但是完全可以接受
创建MyBatis核心配置文件
习惯上命名为mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。将来整合Spring之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。 核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息 核心配置文件存放的位置是src/main/resources目录下
创建Mapper接口
MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类。
- 创建实体类时一定要保证属性名和表的属性一致
相关概念ORM
- 对象:Java的实体类对象
- 关系:关系型数据库
- 映射:二者之间的对应关系
| Java概念 | 数据库概念 |
|---|---|
| 类 | 表 |
| 属性 | 字段/列 |
| 对象 | 记录/行 |
Mapper面向接口编程的两个一致
- 映射文件的namespace要和mapper接口的全类名保持一致
- 映射文件中的SQL语句的id要和mapper接口中的方法名一致
查询功能的标签必须设置resultType或者resultMap
- resultType: 设置默认的映射关系
- resultMap: 设定自定义的映射关系(字段名和属性名不一样/一对多/多对一)
核心配置文件之environment
-
transactionManager:设置事务管理方式
- 属性:
- type="JDBC/MANNAGED"
- JDBC:表示当前环境中,执行SQL时,使用的是JDBC中原生的事务管理方式,事务的提交或回滚需要手动处理
- MANNAGED:表示被管理,例如spring
- 属性:
-
dataSource:配置数据源
- 属性:
- type:设置数据源的类型
- type:“POOLED/UNPOOLED/JNDI"
- POOLED:表示使用数据库连接池缓存数据库连接
- UNPOOLED:表示不使用数据库连接池
- JNDI:表示使用上下文中的数据源
MyBatis中核心配置文件的标签顺序:
设置类型别名 类型别名不区分大小写
<typeAliases>
<typeAlias type="com.sundwich.mybatis.pojo.User" alias="User"></typeAlias>
<!--以包为单位,给包下面的所有类型设置默认的类型别名,即类名切不区分大小写-->
<package name="com.sundwich.mybatis.pojo"/>
<typeAliases>
<mappers>
<!--<mapper resource="mapper/UserMapper.xml"/>-->
<!--
以包为单位引入映射文件
要求:
1. mapper接口所在的包要和映射文件所在的包一致
2. mapper接口要和映射文件的名字一致
-->
</mappers>
//如果不写alias=”User“ 如果不设置该属性,那么该类型拥有默认的别名,即类名且不区分大小写
MyBatis获取参数值的两种方式(重点)
MyBatis获取参数值的两种方式:${}和#{}
-
${}本质是字符串拼接 注意要手动加单引号
-
#{}本质占位符
-
MyBatis获取参数的各种情况
-
mapper接口方法的参数为单个的字面量类型
- 可以通过{}和#{}以任意的字符串获取参数值,但是需要注意{}的单引号问题 ‘${}’
-
MyBatis会将这些参数放到一个map集合中,以两种方式进行存储
- 以arg0、arg1...为键,以参数为值
- 以param1、param2...为键,以参数为值
- 因此只需要通过#{} and {}的单引号
-
若mapper接口方法的参数有多个时,可以手动放到一个map中
- 只需要通过#{} and {}的单引号
-
mapper接口方法的参数是一个实体类类型的参数
- 只需要通过#{}以属性的方式访问属性值即可,但是需要注意${}的单引号问题
-
使用@Param注解命名参数
- 此时MyBatis会将这些参数放在一个map集合中,以两种方式进行存储
- 以@Param注解的值为键,以参数为值
- 以param1、param2...为键
- 此时MyBatis会将这些参数放在一个map集合中,以两种方式进行存储
MyBatis各种查询功能
- 若查询出的数据只有一条
- 可以通过实体类对象
- 可以通过集合来接收结果
- 可以通过map集合接收:字段名为key,值为value
- 若查询出的数据有多条
-
可以通过实体类list集合
-
可以通过map类型的list接收
-
可以在mapper接口的方法上添加@Mapkey注解,此时就可以将每条数据转换的map集合作为值,以某个字段的值作为键,放在同一个map中 exp: @Map("id")
-
MyBatis中设置了默认的类型别名
java.lang.Integer-->int,integer
int-->_int,_integer
Map-->map
string-->string
MyBatis处理模糊查询
复习:MySql like模糊查询使用详解
%:表示任意个或多个字符。可匹配任意类型和长度的字符 like:%三% 三% %三
_ :表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句:_ 可以代表一个中文字符 三_ _三_
在mysql中sql的模式缺省是忽略大小写的
三种方式:
- select * from t_user where username like %${username}%
- select * from t_user where username like "%"#{username}"%"
- select * from t_user where username like concat('%',#{username},'%')
MyBatis处理批量删除
delete * from t_user where id in ({ids}) #{}会自动加单引号,会导致格式不正确 <font color=red>注意不能用#{} 只能用{}
MyBatis处理动态设置表名
sql表名是不能加‘’的 所以只能用${}
select * from ${tablename} ...
添加功能获取自增的主键
useGeneratedKeys:设置当前标签中的sql使用了自增的主键 keyProperty:将自增的主键的值赋值给传输到映射文件中参数的某个属性
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
</insert>
解决字段名和属性名不一致
- 为字段起别名,来保持和属性名一致
- 设置MyBatis的全局配置,将_自动映射为驼峰
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<settings >
<resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
id专门设置主键的映射关系,result设置普通字段映射关系 resultMap: 设置自定义映射关系 id: 唯一标识,不能重复 type: 设置映射关系中的实体类型
子标签: id:设置主键的映射关系 result:设置普通字段的映射关系 属性: property:设置映射关系的属性名,必须是type属性所设置的实体类类型中的属性名 column:设置映射关系中的字段名,必须是sql语句查询出的字段名
通过级联属性赋值解决多对一的映射
-
级联属性赋值
-
association:处理多对一的映射关系 property:需要处理多对的映射关系的属性名 javaType:该属性的类型
-
分步查询 select:设置分步查询的sql的唯一表示(namespace.SQLid或mapper接口的全类名 column:设置分步查询的条件 property:分步查询出来的类型
延迟加载
分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息 lazyLoadingEnable:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载 aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载
fetchType: 当开启了全局的延迟记载以后,可通过此属性手动控制延迟加载的效果 fetchType=“lazy”/“eager”:lazy表示延迟加载,eager表示立即加载
一对多关系
处理一对多的映射关系:
- collection
- collection:处理一对多的映射关系
- ofType:表示改属性所对应的集合中存储数据的类型
- 分步查询
动态SQL
MyBatis框架的动态SQL技术时一种根据特定条件动态拼装SQL语句的功能。它存在的意义是为了解决拼接SQL语句字符串的痛点问题。
动态SQL:
1. if:根据标签中test属性所对应的表达式决定标签中的内容是否需要拼接到SQL中
2. where:当where标签中有内容时,会自动生成where关键字,并且将内容前多余的and或or,当where标签中没有内容时,此时where标签没有任何效果
注意:where标签不能将其中内容后面多余的and或or去掉
3. trim
若标签中有内容时:
prefix|suffix:将trim标签中内容前面或后面添加指定内容
suffixoverrides|prefixoverrides:将trim标签中内容前面或后面去掉指定内容
若标签中没有内容时,trim标签也没有任何效果
4. choose、when、otherwise,相当于if...else if...else
when至少要有一个,otherwise最多只能有一个
5. foreach:
collection:设置需要循环的数组或集合
item:表示数组或集合中的每一个数据
separator:循环体之间的分隔符
open:foreach标签所循环的所有内容的开始符
close:foreach标签所循环的所有内容的结束符
批量删除:
批量添加:
- 记得在接口emps参数前加@Param("emps") 否则无法通过emps访问到这个集合
6. sql标签 设置sql片段: eid,emp_name,age,sex,email 引用sql片段:
MyBatis缓存
一级缓存默认开启
**SqlSession级别 **
一级缓存失效的四种情况:
- 不同的SqlSession对应不同的一级缓存
- 同一个SqlSession但是查询条件不同
- 同一个SqlSession两次查询期间执行了任何一次增删改操作(任何的增删改操作都会直接清空缓存)
- 在两次查询之间手动清空了缓存
MyBatis的二级缓存
**SqlSessionFactory级别 ** 二级缓存开启的条件:
- 在核心配置文件中,设置全局配置属性CacheEnabled=“true”,默认为true,不需要设置
- 在映射文件中设置标签
- 二级缓存必须在SqlSession关闭或提交之后有效
- 查询的数据所转换的实体类类型必须实现序列化的接口
二级缓存失效的情况: 任何增删改查都会清空一级和二级缓存 Cache Hit Ratio缓存命中率
二级缓存相关配置
- eviction属性:缓存回收策略
- LRU(Least Recently Used) -最近最少使用的
- FIFO(First in First Out)
- SOFT -软引用:移除基于垃圾回收器状态和软引用规则的对象
- WEAK -弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象 默认的是LRU
- flushInterval属性:刷新间隔,单位毫秒 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句(增删改)时刷新
- size属性:引用数目,正整数 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
- readOnly属性:只读 true/false
- true:只读缓存:会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
- false:读写缓存:会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
MyBatis缓存查询的顺序
- 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
- 如果二级缓存没有命中,在查询一级缓存
- 如果一级缓存也没有命中,则查询数据库
- SqlSession关闭之后,一级缓存的数据会写入二级缓存
整合第三方缓存EHCache
MyBatis提供了缓存接口,可以用第三方缓存来替代二级缓存(一级缓存是没办法替代的)
- 添加依赖
2. 各jar包功能
-
创建EHCache的配置文件ehcache.xml
-
设置二级缓存的类型
-
加入logback日志配置文件
MyBatis的逆向工程
- 正向工程:先创建Java实体类,由框架负责根据实体类生成数据库,Hibernate是支持正向工程的
- 逆向工程:先创建数据库,由框架负责根据数据库表,反向生成如下资源
- Java实体类
- Mapper接口
- Mapper映射文件
- 创建逆向工程的步骤
- 创建MyBatis核心配置文件
- 创建逆向工程
-
文件名必须是:generatorConfig.xml
-
分页插件
- 分页插件使用步骤
a> 添加依赖
b> 配置分页插件 在MyBatis的核心配置文件中配置插件
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageIntegerceptor"></plugin>
</plugins>
分页相关的内容: limit index,pageSize index:当前页的起始索引 pageSize:每页显示的条数 pageNum:当前页的页码 index=(pageSize*(pageNum-1)
使用MyBatis的分页插件实现分页功能:
-
需要在查询功能之前开启分页 pageHelper.startPage(int PageNum,int pageSize);
-
在查询功能之后获取分页相关信息 pageInfo page=new pageInfo<>(list,5); list表示分页数据 5表示当前导航分页的数量 navigatePageNums: 导航栏一共有的页面数字的个数