最近接了个xxx代码.

不能说人家不好, 因为必进年月久了.能用这么长时间, 不就说明还不错么?! 我们现在每天写的, 能超出人家的么~~~ 呵呵

Java项目中, 把动态数据源切换的框架整合进来. 嗯...这个有好有不好吧.

按Service层使用AOP来切换主从. 但是企业应用非常复杂. 如果再加一个别的数据库连接进来, 框架就显得不够用.

而框架的修改权又掌握在某一个部门手中, 所以,只能类似补丁地融入. 所以有了这一上午走读Spring/MyBatis的机会. 也挺好.

SpringBoot的一个annotation @SpringBootApplication, 使用其 exclude, 把框架中的某一些 @Configuration 排除掉.

然后自己写子类继承这些原有的@Configuration类, 并且加上@Configuration.
然后就可以初始化了.
原有容器初始化的时候, 以@Bean的方式生产了SqlSessionFactory, 默认执行Mapper的时候就会使用.
所以,如果用新加进来的DataSource也生成@Bean SqlSessionFactory, 那么Mapper就会迷茫,因为默认是按类型查找SqlSessionFactory.
解决这个问题, 改框架动静太大. 简单一点, 把原来的@Bean SqlSessionFactory加上@Primary,为默认. 然后新数据库连接使用的时候,可以使用
@Autowired @Quirified("xxx") 来注入SqlSessionFactory, 然后在@PostConstruct里, 把SqlSessionTemplate获取到,
然后,可以使用 sqlSessionTemplate.getMapper(Xxx.class) 获取到 Mapper.class接口的代理实例.
在这里踩了一个坑, 就是 getMapper总是说没有注册. 于是追踪了一下Mapper的注册过程.

有几篇blog写得挺好. 但是太冗长
Mybatis初始化加载流程————配置文件解析
https://blog.csdn.net/u011043551/article/details/80607050
Mybatis 源码学习(一) Mapper 注册
https://blog.csdn.net/tiantiandjava/article/details/80569451 Mybatis初始化加载流程————Mapper接口注册
https://blog.csdn.net/u011043551/article/details/80619319 关键点: SqlSessionFactoryBean 是建造者模式, 设置了一堆属性之后, 然后调用 getObject()的时候,
执行
afterPropertiesSet();-->buildSqlSessionFactory(); --> 一大段.
这大段代码的基本逻辑有3点:
1.注册Class, 基本上是Example, DTO 等等.
2.注册plugins, 比如翻页插件就在这里注册
3.注册handler, 这一段没特别了解, 后面用到再看看
4.注册xml, xmlConfigBuilder.parse()
这一段包含了这次的内容. 一大段.
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
基本是解析xml各个节点.
其中mapperElement 这个方法里,
把xml节点中mapper 进行解析.调用mapperParser.parse();(XMLMapperBuilder) ---> bindMapperForNamespace();
private void bindMapperForNamespace() {
String namespace = builderAssistant.getCurrentNamespace();
if (namespace != null) {
Class<?> boundType = null;
try {
boundType = Resources.classForName(namespace);
} catch (ClassNotFoundException e) {
//ignore, bound type is not required
}
if (boundType != null) {
if (!configuration.hasMapper(boundType)) {
// Spring may not know the real resource name so we set a flag
// to prevent loading again this resource from the mapper interface
// look at MapperAnnotationBuilder#loadXmlResource
configuration.addLoadedResource("namespace:" + namespace);
configuration.addMapper(boundType);
}
}
}
}
会把xml中namespace中写着的xxx.xxx.Mapper认为是类, 来加载注册!!! 藏得真是深. 参考了:
Spring读取mybatis在多个jar包下的的mapper文件
https://blog.csdn.net/zixuan0104/article/details/54601563

primary这个翻译过来是 首要的,首选的意思。
primary的值有true和false两个可以选择。默认为false。
当一个bean的primary设置为true,然后容器中有多个与该bean相同类型的其他bean,
此时,当使用@Autowired想要注入一个这个类型的bean时,就不会因为容器中存在多个该类型的bean而出现异常。而是优先使用primary为true的bean。
不过,如果容器中不仅有多个该类型的bean,而且这些bean中有多个的primary的值设置为true,那么使用byType注入还是会出错。

https://blog.csdn.net/qq_36951116/article/details/79130591

https://www.cnblogs.com/dongying/p/4142476.html

希望Mapper自动分了数据源, 需要在MapperScan上加上ref

@MapperScan(basePackages="com.XXX.bpaas.idm.mapper.dao", sqlSessionTemplateRef = "idmSqlSessionTemplate")

@MapperScan(basePackages="com.XXX.bpaas.idm.mapper.dao", sqlSessionFactoryRef = "xxxFactory"), 这样就可以在注册每个Mapper的时候,匹配到正确的数据源.

主从切换的数据源是在线程切换层次, 不会影响到这里.

MapperScan决定xxxMapper.select 使用 那个xxxxFactory, 执行时, 如果该数据源有主从切换,读写分离,在ThreadLocak<Holder>中切换变量值就OK了.

>>参照了

https://blog.csdn.net/mxw2552261/article/details/78640062   good

https://blog.csdn.net/weixin_40562217/article/details/82840764   good

https://www.cnblogs.com/dongying/p/4142476.html

https://www.cnblogs.com/dongying/p/4040435.html

下一步研究一下, 事务传播, 两个数据源的@Transactional 嵌套时有什么问题.

https://www.cnblogs.com/Kidezyq/p/8541199.html    采坑

https://www.cnblogs.com/zishengY/p/6850673.html   多个事务管理器

MyBatis SpringBoot 杂记的更多相关文章

  1. springboot(三 使用mybatis +springboot 完成简单的增删改查)

    先说一些注解: @EnableAutoConfiguration 可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器 ...

  2. yml的mybatis的sql查看;Mybatis+Springboot 控制台查看日志,Mybatis结合springboot打印日志

    1.配置如图 文件为yml mybatis: mapper-locations: classpath:com/springboot/transaction/mapper/*.xml configura ...

  3. IntelliJ IDEA 2017版 spring-boot2.0.4+mybatis反向工程;mybatis+springboot逆向工程

    一.搭建环境 采用IDE自动建立项目方式 然后,next next,配置导入依赖包 项目就生成了,在项目下导入配置文件GeneratorMapper.xml(项目结构如图所示) 配置文档,建立数据库和 ...

  4. SpringBoot杂记

    一.配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.properties •application.yml 配置文件的作用:修改SpringBoo ...

  5. Mybatis+SpringBoot 项目All elements are null

    xml文件内容如下 查出来的集合长度是有的,但是会出现All elements are null 解决方案: 注意我的xml文件全部是这样的,并且我调用的sql返回值是  resultType=&qu ...

  6. SpringBoot+Mybatis集成搭建

    本博客介绍一下SpringBoot集成Mybatis,数据库连接池使用alibaba的druid,使用SpringBoot微框架虽然集成Mybatis之后可以不使用xml的方式来写sql,但是用惯了x ...

  7. Springboot mybatis generate 自动生成实体类和Mapper

    https://github.com/JasmineQian/SpringDemo_2019/tree/master/mybatis Springboot让java开发变得方便,Springboot中 ...

  8. SpringBoot集成MyBatis的Bean配置方式

    SpringBoot集成MyBatis的Bean配置方式 SpringBoot是一款轻量级开发的框架,简化了很多原先的xml文件配置方式,接下来就介绍一下如何不适用XML来配置Mybatis spri ...

  9. MyBatis原理,Spring、SpringBoot整合MyBatis

    1. MyBatis概述 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可 ...

随机推荐

  1. 小a的轰炸游戏 (差分)

    我是看题解的! 这道题还是有很多细节,当然,是一道差分的好题! 题意:有2种飞机,一种是只炸上半菱形,一种是炸整个菱形.问所有区域内的所有格子的异或和. 思路:用前缀和思路: 这样遍历过去就完成了一次 ...

  2. Linux Driver 开发 eclipse工程找不到头文件

    如下添加头文件路径, 右键单击工程,选择 Properties  >  C/C++ Build  >  Settings  >  >  GCC C/C++ Compiler  ...

  3. LeetCode264:Ugly Number II

    自己的做法超时了.主要是每次生成一个数据,保存到list中,然后对List重新排序.排序太耗费时间 记录下讨论组里的写法 public int NthUglyNumber(int n) { int[] ...

  4. Gym101138D Strange Queries/BZOJ5016 SNOI2017 一个简单的询问 莫队、前缀和、容斥

    传送门--Gym 传送门--BZOJ THUWC2019D1T1撞题可还行 以前有些人做过还问过我,但是我没有珍惜,直到进入考场才追悔莫及-- 设\(que_{i,j}\)表示询问\((1,i,1,j ...

  5. A2D JS框架 - loadScript实现

    其实这个功能比较小,本着自己造轮子的优良传统....就自己造一个好了 <head> <title></title> <script src="A2D ...

  6. HBase篇(4)-你不知道的HFile

    [每日五分钟搞定大数据]系列,HBase第四篇 这一篇你可以知道, HFile的内部结构? HBase读文件细粒度的过程? HBase随机读写快除了MemStore之外的原因? 上一篇中提到了Hbas ...

  7. 朱晔和你聊Spring系列S1E10:强大且复杂的Spring Security(含OAuth2三角色+三模式完整例子)

    Spring Security功能多,组件抽象程度高,配置方式多样,导致了Spring Security强大且复杂的特性.Spring Security的学习成本几乎是Spring家族中最高的,Spr ...

  8. CSS 定位 (Positioning) 实例

    CSS 定位和浮动CSS 为定位和浮动提供了一些属性,利用这些属性,可以建立列式布局,将布局的一部分与另一部分重叠,还可以完成多年来通常需要使用多个表格才能完成的任务. 定位的基本思想很简单,它允许你 ...

  9. vertical-align和图片下方空白问题

    <style> .box1,.box2{ display: inline-block; background-color:#f0f3f9; width:150px; height: 150 ...

  10. java----牛客练习

    1. 形式参数就是函数定义时设定的参数.例如函数头 int min(int x,int y,int z) 中 x,y,z 就是形参.实际参数是调用函数时所使用的实际的参数.   真正被传递的是实参   ...