mybatis是一个优秀的开源框架,半自动ORM映射,能够适配各种业务需求
mybatis路线图(下)
- MyBatis的多表联合查询(了解一对一,熟练一对多(理解延迟加载),熟练多对多)
- MyBatis的动态SQL(嵌套的语句的几种方式,按需使用)
- MyBatis中#{}${}之间的区别
- MyBatis的延迟加载(什么是延迟加载,好处,场景)
- MyBatis的缓存机制(缓存机制策略,一级缓存和二级缓存的不同,二级缓存的实现)
- MyBatis逆向工程(了解逆向工程,思考不方便的地方)
MyBatis的多表联合查询
1对1的说明:在级联关系中OneToOne是比较不太频繁出现的一种情况(在数据库设计上面可以考虑共用主键关系,或者利用一对多进行变种实现,利用外键可设置唯一约束UNIQUE约束),我们应该专注sql语句,追求高度自由化,虽然mybatis提供一对一的关联设置,但是我们还是利用一对多的方式进行变种实现
引用:级联不是必须的,级联的好处是获取关联数据十分便捷,但是级联过多会增加系统的复杂度,同时降低系统的性能,此增彼减,所以当级联的层级超过3层时,就不要考虑使用级联了,因为这样会造成多个对象的关联,导致系统的耦合,复杂和难以维护.在现实的使用过程中,要根据实际情况判断是否需要使用级联.
1对m的实现方式与m对1实现方式:(场景:1个用户有多个贴子,多个帖子的著作人)
表和实体关系说明:user表和post表为1:M的关系
实体代码如下:自行get和set
1 | public class User { |
- 接口和mapper映射内容操作如下
1 | /** |
接下来是多对一的实现也就是在站在帖子这一边,展现帖子的时候希望看到著作人是谁(注意:实体会发生一点小的变动,在post属性中添加user属性)
1 | public interface PostDao { |
下面是多对多上面的操作场景(一个用户可以有多个兴趣,一个兴趣可能有多个人选择)
构建二个实体分别是animal和interest和第三方表(animal_interest)
- 创建一个第三方表的映射接口(animal_interestDao)和映射的实现(animal_interestMapper.xml)
1 | /** |
- 分别构建AnimalDao和InterestDao以及映射文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//获取用户信息
List<Animal> getAnimals();
//-------
<mapper namespace="com.wwj.dao.AnimalDao">
<!-- 定义一对多的resultmap -->
<resultMap type="com.wwj.model.Animal" id="animals1">
<id property="aid" column="aid" />
<result column="uname" property="uname" />
<collection property="interests" column="aid" select="com.wwj.dao.Animal_InterestDao.getInterestByAid">
</collection>
</resultMap>
<select id="getAnimals" resultMap="animals1" >
select a.*
from animal a
</select>
</mapper>
1 | public interface InterestDao { |
MyBatis的动态SQL
模拟一张用户表进行说明,以及代码说明
1 | public interface TestUserDao { |
1 | <?xml version="1.0" encoding="UTF-8"?> |
MyBatis中#{}和${}区别
简单的说#{}是采用占位符的方式,而$是采用是字符串拼接的方式
字符串拼接的方式就一定会存在sql注入的问题
MyBatis的延迟加载
(延迟加载===按需加载)
- 比如刚才的一个用户有多个兴趣,现在需要用户信息的时候,编写sql语句的时候同时也把暂时不需要看用户的兴趣的数据加载出来,在数据量大的情况就肯定有瓶颈。
- 所以我们可以参照多对多示例中进行设置延迟加载,来观察sql语句的发出
1 | //代码示例如下: 我仅仅需要用户信息,但是同样的也把其它非相关的信息加载出来了 |
- 配置延迟加载
全局配置文件中配置添加
1 | <settings> |
MyBatis的缓存机制
- 一级缓存(缓存不相互共享,在同一个事务中,如果存在同样的操作,中间不带增删改操作的话。那么不在进行二次IO读取操作)
1 | List<Animal> as =session.selectList("getAnimals"); |
- 二级缓存(缓存共享)需要映射的接口对应的映射文件加入:
1 | <mapper namespace="com.wwj.dao.AnimalDao"> |
1 | SqlSession session = build.openSession(); |
1 | //-----控制台结果 |
(缓存机制策略的补充)
- 默认mybatis映射语句文件中所有的select语句将会被缓存
映射语句文件中所有的insert update delete 语句会刷新缓存
缓存会使用(Least Flush Interval,LRU最近最少使用的)算法来收回
根据时间表(如 no Flush Interval,没有刷新间隔),缓存不会以任何时间顺序来刷新 - eviction(收回策略===更新策略)
LRU 最近最少使用的,移除最长时间不被使用的对象,这是默认值 FIFO 先进先出,按对象进入缓存的顺序来移除它们 SOFT 软引用,移除基于垃圾回收器状态和软引用规则的对象 WEAK 弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象
- 缓存存在数据可能出现脏读的现象(操作同一数据)缓存数据尽量用在变更不频繁的数据上面
影响缓存的三个因素(缓存更新策略,缓存最大数据量,命中率)
MyBatis逆向工程
- 逆向工程我们做简单的展示
- 逆向工程的含义在于根据数据库的表的结构以面向对象的方式自动的帮助我们生成对应的实体类
- 逆向为什么不太常用,因为一旦数据库的结构和关联发生变化,那么实际开发过程中就需要自己手动调整对应的实体类,这个可以说是一个非常浩瀚的工程,无论从人力和无力成本看来都得不偿失
- 以前我们可以说小的项目,用逆向比较方便,不如我们把逆向看成是不可取的,mybatis本身也是追求语句的自由化。所以逆向作为了解即可.
- 引入对应的jar包
- 构建逆向配置xml文件generatorConfig.xml位置在项目外
1 | <?xml version="1.0" encoding="UTF-8"?> |
- 构建生成main函数
1 | public class TestG { |