关于Mybatis与Spring整合以后SqlSession与mapper对象之间数量的问题。

1,sqlsession的真实类型和数量

因为使用spring管理bean,当咱们在代码中须要使用这个bean的时候,会首先去容器中找,第一次须要调用MapperFactoryBean的getObject方法获取一个bean,并保存到容器中。spring

MapperFactoryBean的getObject方法以下:sql

 

因为每一个MapperFactoryBean对象初始化的时候,都会建立一个sqlSession,代码在MapperFactoryBean类的父类SqlSessionDaoSupport中,当spring向MapperFactoryBean对象中注入SqlSessionFactory时就建立了SqlSession:数据库

 

【结论1】:一个MapperFactoryBean对象拥有一个sqlSession对象。类型是org.mybatis.spring.SqlSessionTemplate缓存

重要:spring整合mybatis使用的sqlSession类型是org.mybatis.spring.SqlSessionTemplatesession

那么整合后的mybatis是怎么执行的呢?mybatis

首先查看SqlSessionTemplate类能够看到,全部的数据库执行都被一个动态代理的sqlsession对象代理了。app

 

在构造方法中查看该代理对象的构造spa

使用JDK动态代理,实现InvocationHandler的类是SqlSessionIntercepteor,查看它的invoke方法以下:3d

 

能够看到,方法开始就直接建立了一个新的sqlsession对象,这个对象就是被代理的对象。代理

再看getSqlSession方法,它是SqlSessionUtils中的一个静态方法,以下:

 

第一句话和事务有关,若是它返回空,则直接使用sessionFactory建立一个新的session

【结论】spring整合mybatis后,非事务环境下,每次操做数据库都使用新的sqlSession对象。所以mybatis的一级缓存没法使用(一级缓存针对同一个sqlsession有效)

下面两段代码:

(1)不整合spring,以下代码的输出能够看出,使用了一级缓存

 

结果:查询过程只执行了一次。

 

(2)整合spring,

 

输出结果以下:

 

两次的输出表示没有使用一级缓存。

2,Mapper接口对应的bean在容器中的数量

经过getObject返回的对象是单利的,从MapperFactoryBean的isSingleton()能够得出

 

【结论二】所以,同一个IOC容器中同一个Mapper接口对应的代理类只有一个

例如系统有一个UserMapper接口对应UserMapper.xml

则以下代码返回true

 

相关文章
相关标签/搜索