关于mybatis的一些总结

常用标签

select|insert|updae|delete|resultMap|parameterMap|sql|include|selectKey

其中<sql>为sql片段标签,通过<include>标签引入sql片段,<selectKey>为不支持自增的主键生成策略标签。

动态标签

trim|where|set|foreach|if|choose|when|otherwise|bind

trim标签

四个属性:prefix,prefixOverrides,suffix,suffixOverrides

1、prefix,suffix 表示在trim标签包裹的部分的前面或者后面添加内容(注意:是没有prefixOverrides,suffixOverrides的情况下,prefix与prefixOverrides对应,suffix与suffixOverrides对应)

2、如果有prefixOverrides,suffixOverrides 表示覆盖Overrides中的内容。
3、如果只有prefixOverrides,suffixOverrides 表示删除。(这里的“只有”表示prefixOverrides没有对应的prefix,suffixOverrides没有对应的suffix情况下,比如只有prefix和suffixOverrides情况或者只有suffix和prefixOverrides情况下也表示删除)

标签resultid区别

id比起result的多了一个承担着标识对象的功能,即只需要判断id标识的属性就可以判断两个对象的异同。

Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;原因就是namespace+id是作为Map<String,MapperStatement>的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。

联合查询

select * from A left join B on A.id=B.id  该语句出来的数据是A表数据和B表数据的集合

association:单个对象关联

collection:多个对象关联

Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。

缓存机制

mybatis有二级缓存

一级缓存是sqlsession级别的(单个sqlsession),二级缓存是共享多个sqlsession,namespace级别的。

MyBatis 提供了一级缓存的方案优化这部分场景,如果是相同的 SQL 语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能每个 SqlSession 中持有了 Executor,每个 Executor 中有一个 LocalCache。当用户发起查询时,MyBatis 根据当前执行的语句生成 MappedStatement,在 Local Cache 进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入 Local Cache,最后返回结果给用户。

1. MyBatis 一级缓存的生命周期和 SqlSession 一致。

2. MyBatis 一级缓存内部设计简单,只是一个没有容量限定的 HashMap,在缓存的功能性上有所欠缺。

3. MyBatis 的一级缓存最大范围是 SqlSession 内部,有多个 SqlSession 或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为 STATEMENT。

注:一级缓存的缓存级别有两个选项,SESSION和STATEMENT,默认是SESSION级别,即在一个Mybatis会话中执行的所有语句,都会共享这一个缓存。一种是STATEMENT级别,可以理解为缓存只对当前执行的这一个statement有效。

如果多个 SqlSession之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用 CachingExecutor 装饰Executor,进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询,二级缓存开启后,同一个 namespace 下的所有操作语句,都影响着同一个 Cache,即二级缓存被多个 SqlSession 共享,是一个全局的变量。

数据的查询执行的流程为

二级缓存 -> 一级缓存 -> 数据库

1. MyBatis 的二级缓存相对于一级缓存来说,实现了 SqlSession 之间缓存数据的共享,同时粒度更加细,能够到 namespace 级别,通过 Cache 接口实现类不同的组合,对 Cache 的可控性也更强。

2. MyBatis 在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。

3. 在分布式环境下,由于默认的 MyBatis Cache 实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将 MyBatis 的 Cache 接口实现,有一定的开发成本,直接使用 Redis、Memcached 等分布式缓存可能成本更低,安全性也更高。

使用mybatis的两种方式:

1、mybatis提供的API

使用Mybatis提供的API进行操作,通过获取SqlSession对象,然后根据Statement Id 和参数来操作数据库。

String statement = "com.mmzsblog.business.dao.MemberMapper.getMemberList";
List<Member> result = sqlsession.selectList(statement);

2、mapper接口

 定义Mapper接口,并在里面定义一系列业务数据操作方法。在Service层通过注入mapper属性,调用其方法就可以执行数据库操作。

public interface MemberMapper {	
	List<Member> getMemberList();
}

@Service
public class MemberServiceImpl implements MemberService{
	@Resource
	private MemberMapper memberMapper;
	
	@Override
	public List<Member> getMemberList() {
		return memberMapper.getMemberList();
	}
}
MyBatis中Mapper接口是怎么和XML文件关联起来的(待补充

解析mapper的XML文件,通过xmlMapperBuilder的parse方法进行,构建 statement,然后将其添加进 mappedStatements 缓存中(每一个SQL标签就对应一个MappedStatement对象,更准确来说是sqlSource对象),mappedStatements 数据结构是一个 StrictMap(注:strict严格的),这个 StrictMap 不允许有重复的 key,而存入的 key 就是 statement 中的 id。因此 Mapper 接口中的方法不能重载(注:id为全限类名+方法名,举例如com.google.dao.UserMapper.batchAddUser)

mybatis的mapper接口中的方法为什么没有实现类也可以实现调用?

Configuration加载了mybatis所有配置,其中mapperRegistry会加载mapper文件(反射机制生成mapper对象),通过mapperRegistry的getMapper方法可以获取mapper代理工厂MapperProxyFactory,具体是通过knownMappers(已加载的mapper的Map集合)来获取代理工厂对象,然后生成动态代理返回,具体为MapperProxyFactory的newInstance方法,入参为MapperProxy对象,把sqlSession, mapperInterface, methodCache三个参数封装到MapperProxy中,而MapperProxy是实现了InvocationHandler接口的方法,因此动态代理被调用的时候,会进入到MapperProxy的invoke方法中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值