当前位置: 首页 > news >正文

Mybatis源码研究之DatabaseIdProvider

借助Mybatis提供的 databaseId特性,我们可以实现让应用同时支持多种类型的数据库。

0. 目录这里写目录标题

      • 1. 测试用例
      • 2. 原理解析
      • 3. databaseId的其它应用
      • 4. Links

1. 测试用例

相关的配置和测试用例如下 (这里我们以源生的mybatis为例,与SpringBoot的集成留待读者自行解读):

  1. mybatis-config.xml配置文件
    <environments default="development"><environment id="development">....</environment></environments><!-- 启用databaseId支持 --><databaseIdProvider type="DB_VENDOR"><property name="Oracle" value="oracle"/></databaseIdProvider>	    <mappers>......</mappers>
  1. Mapper类
// Mapper
public interface MultiDbTestMapper {int getMtHisTableExists(@Param("dbName") String dbName, @Param("tableName") String tableName);
}
  1. Mapper文件
// mapper xml
<mapper namespace="xxx.mapper.MultiDbTestMapper"><!-- 查看某表是否存在 --><select id="getMtHisTableExists" resultType="java.lang.Integer">select count(*) ICOUNT from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=#{dbName} and TABLE_NAME=upper(#{tableName})</select><!-- oracle方言查看某表是否存在 --><select id="getMtHisTableExists" resultType="java.lang.Integer" databaseId="oracle">SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME=upper(#{tableName})</select><!-- sqlserver方言查看某表是否存在 --><select id="getMtHisTableExists" resultType="java.lang.Integer" databaseId="sqlserver">select count(*) from dbo.sysobjects where id = object_id(upper(#{tableName})) and OBJECTPROPERTY(id, N'IsUserTable') = 1</select></mapper>
  1. 测试用例。
    @Autowiredprivate MultiDbTestMapper mapper;@Testpublic void testName() throws Exception {Console.log(mapper.getMtHisTableExists("xxx_boot", "xxx_code"));}     
  1. 用例执行结果:
    1. mybatis将根据实际配置的数据库地址,从相同id的映射语句(<select>/<insert>/<update>/<delete>)中抓取相对应的进行执行。
    2. 以上操作由mybatis自行完成,使用者只需要正确配置数据库链接即可。无需其他额外操作。

2. 原理解析

先说结论:

  1. mybatis在启动阶段,根据数据源的配置,将xml映射文件中对应数据库类型的 xml节点语句加载到内存中,以供之后的调用。
  2. 以上述"getMtHisTableExists"为例,只会有其中一个被加载到内存中。

源码解读:

  1. 与当前环境下所使用的DataBase相适应的databaseId的获取。

    //================= XMLConfigBuilder.databaseIdProviderElement() , 对应于上述测试用例中mybatis-config.xml的配置
    //  1. 以下方法将为 Configuration 中的 databaseId 字段赋值。
    //  2. 赋值逻辑大致是通过用户注册的自定义DatabaseIdProvider实现类来完成
    //  3. DatabaseIdProvider默认实现为 VendorDatabaseIdProvider . 其中databaseId的获取逻辑为:根据实际的DataSource类型来获取配置的对应databaseIdprivate void databaseIdProviderElement(XNode context) throws Exception {DatabaseIdProvider databaseIdProvider = null;if (context != null) {String type = context.getStringAttribute("type");// awful patch to keep backward compatibilityif ("VENDOR".equals(type)) {// 在 Configuration 的构造函数中注册type = "DB_VENDOR";}Properties properties = context.getChildrenAsProperties();databaseIdProvider = (DatabaseIdProvider) resolveClass(type).getDeclaredConstructor().newInstance();databaseIdProvider.setProperties(properties);}Environment environment = configuration.getEnvironment();if (environment != null && databaseIdProvider != null) {// 从实际使用的数据源中获取当前适用的databaseIdString databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());configuration.setDatabaseId(databaseId);}}
    
  2. databaseId生效。

    //================= XMLStatementBuilder.parseStatementNode()public void parseStatementNode() {String id = context.getStringAttribute("id");String databaseId = context.getStringAttribute("databaseId");// 如果当前 <select>/<update>/<insert>/<delete>节点上的 databaseId 属性值 与 全局配置上的 databaseId 不一致, 则直接跳过对其的解析, 不会将其加载到内存中if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {return;}String nodeName = context.getNode().getNodeName();......}private boolean databaseIdMatchesCurrent(String id, String databaseId, String requiredDatabaseId) {if (requiredDatabaseId != null) {return requiredDatabaseId.equals(databaseId);}if (databaseId != null) {return false;}id = builderAssistant.applyCurrentNamespace(id, false);if (!this.configuration.hasStatement(id, false)) {return true;}// skip this statement if there is a previous one with a not null databaseIdMappedStatement previous = this.configuration.getMappedStatement(id, false); // issue #2return previous.getDatabaseId() == null;}
    

3. databaseId的其它应用

  1. databaseId的另外一种使用方式: @Select注解。

    
    // 注解的方式实现SQL, 效果等同于上述测试用例中的映射文件
    // 底层支撑类: MapperAnnotationBuilder.AnnotationWrapper
    @Select(value = "select count(*) ICOUNT from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=#{dbName} and TABLE_NAME=upper(#{tableName})", databaseId = "mysql")
    @Select(value = "SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME=upper(#{tableName})", databaseId = "oracle")
    int getMtHisTableExistsByAnnotation(@Param("dbName") String dbName, @Param("tableName") String tableName);
    
  2. 通过占位符,在映射语句中获取当前的databaseId。(支撑类为DynamicContext

    <select id="getMtHisTableExists" resultType="java.lang.Integer" databaseId="oracle">SELECT '${_databaseId}' as databaseId FROM USER_TABLES WHERE TABLE_NAME=upper(#{tableName})      
    </select>
    

4. Links

  1. spring boot项目中mybatis plus多数据库支持
  2. MyBatis之databaseIdProvider多数据库支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-2879.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

学生成绩管理系统+打包

文章目录文件管理&#xff1a;D:\hyt\python\pytorch_graduate\file_management成绩管理&#xff1a;D:\hyt\python\pytorch_graduate\stusystem打包&#xff1a;D:\hyt\python\pytorch_graduate\package_test学生成绩管理系统0.基础原理1.文件管理2 学生管理系统Tk打包1.基础原…...

Yocto Build with Bitbake的调试

https://docs.yoctoproject.org/dev-manual/common-tasks.html#recipe-logging-mechanisms 官方文档里有输出调试信息的方法。包含两种&#xff0c;一种是调用python的&#xff0c;一种是bash的。 建议直接使用warning方法&#xff0c;保证输出级别足够。 另外&#xff0c;在…...

IntentService源码分析指南

转载链接&#xff1a;https://www.jianshu.com/p/8a3c44a9173a...

为啥集群小文件治理那么重要,你真的懂吗?

小文件是 Hadoop 集群运维中的常见挑战&#xff0c;尤其对于大规模运行的集群来说可谓至关重要。如果处理不好&#xff0c;可能会导致许多并发症。Hadoop集群本质是为了TB,PB规模的数据存储和计算因运而生的。为啥大数据开发都说小文件的治理重要&#xff0c;说HDFS 存储小文件…...

Flink大数据实时计算系列-第一个程序JAVA版本-分组统计

Flink大数据实时计算系列-第一个程序JAVA版本-分组 在基线版本上增加了分组统计的代码 #Flink代码 package com.flinkniu.flink.operator;import org.apache.flink.api.common.typeinfo.Types; import org.apache.flink...

Ant Design Vue实现a-table表格单元格合并

Ant Design Vue实现a-table表格单元格合并 参考Ant design Vue官网关于行和列合并api https://antdv.com/components/table-cn/ 下面官网对表格合并这块的描述 &#xff01;&#xff01;&#xff01;注意注意注意重要事情说三遍&#xff1a;很多同学都习惯性的将columns写在d…...

【CoppeliaSim】Solidworks中模型导出模型到V-REP

一、下载安装插件 插件名称&#xff1a;sw2urdfSetup 下载地址&#xff1a;https://github.com/ros/solidworks_urdf_exporter/releases/tag/1.6.0 下载后直接安装即可。安装成功后&#xff0c;可在SolidWorks的菜单栏中看到&#xff1a;工具-Tools-Export as URDF 二、导出…...

css中id和class的区别

css中id和class的区别ID是唯一的类不是唯一的语法区别ID是唯一的 每个元素仅可以有一个ID每个页面仅可以有一个元素拥有这个ID 类不是唯一的 你可以在多个元素中使用相同的类你可以使用多个类在一个元素中 语法区别 id对应css是用样式选择符“#”&#xff08;井号&#xff…...

力扣刷题:动态规划篇

目录322. 零钱兑换题目介绍题目实现5. 最长回文子串题目介绍题目实现518. 零钱兑换 II题目介绍题目实现53. 最大子序和题目介绍题目实现63. 不同路径 II题目介绍[62. 不同路径](https://leetcode-cn.com/problems/unique-paths/)题目实现70. 爬楼梯题目介绍题目实现72. 编辑距离…...

Java面试list 和 set 区别

List和Set的区别 List:&#xff1a;有序&#xff0c;按对象进入的的序保存对象&#xff0c;可可允许多个Null元素对象&#xff0c;可以使用lterator迭取出所有元素。在逐一便历&#xff0c;也可以使用get(int index)获取指定下标的元素 Set&#xff1a;无序&#xff0c;不可重复…...

诚意分享:这里有份超全Java体系化进阶学习图谱

摘要 Apache Kafka是一个分布式消息发布订阅系统。它最初由LinkedIn公司基于独特的设计实现为一个分布式的提交日志系统( a distributed commit log)&#xff0c;之后成为Apache项目的一部分。 成千上万的企业都在使用Kafka&#xff0c;三分之一的世界500强公司也在其中&…...

requests+re爬取猫眼电影排行

import requests from requests.exceptions import RequestException import re,json,timedef get_one_page(url):#获取网页信息try:headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/53…...

Twitter教程:如何下载Twitter数据副本?

Twitterrific Mac破解版是一款非常现代化优秀的桌面Twitter客户端,这款软件不仅看起来惊人,它的表现也是非常棒的,本文给大家的带来了如何下载Twitter数据副本的教程。 教程如下 在 iPhone 或 iPad 上打开“Twitter”。&#xff08;您也可以使用 Twitter.com 网站&#xff09…...

4-1 Python常用内置算法与数据结构常考题

一、你使用过哪些常用内置算法和数据结构 仔细回想一下你用过哪些内置的算法数据结构&#xff1f; 1.sorted 2.dict/list/set/tuple… 3.问题&#xff1a;想的不全或者压根没了解和使用过 数据结构/算法语言内置内置库线性结构list(列表)/tuple(元组)array(数组&#xff0c;不…...

【内网学习笔记】8、powercat 的使用

1、下载安装 powercat powercat 可以视为 nc 的 powershell 版本&#xff0c;因此也可以和 nc 进行连接。 powercat 可在 github 进行下载&#xff0c;项目地址为&#xff1a;https://github.com/besimorhino/powercat 下载下来 powercat.ps1 文件后&#xff0c;直接导入即可…...

栈和队列(二) : 用栈实现队列

leetcode232.用栈实现队列 https://leetcode-cn.com/problems/implement-queue-using-stacks/ 使用栈实现队列的下列操作&#xff1a; push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。…...

CentOS 配置php环境

一.安装apache 1.安装apache yum install httpd2.修改配置文件 vi /etc/httpd/conf/httpd.conf将#ServerName www.example.com:80前面的#去掉 修改为ServerName localhost:80 3.添加端口,刷新配置,并查看确认 firewall-cmd --permanent --zonepublic --add-port80/tcp fire…...

测试技巧:弱网测试

弱网测试场景 当前APP网络环境比较复杂&#xff0c;网络制式有2G、3G、4G网络&#xff0c;还有越来越多的公共Wi-Fi。不同的网络环境和网络制式的差异&#xff0c;都会对用户使用app造成一定影响。另外&#xff0c;当前app使用场景多变&#xff0c;如进地铁、上公交、进电梯等…...

PMP哪里报名

首先了解下PMP考试时间&#xff0c;一年四次&#xff0c;正常情况是每年3、6、9、12月份考试&#xff1b; 其次了解PMP考试需要两次报名&#xff0c;分别是英文报名和中文报名&#xff1b;且两次报名通过后&#xff0c;才能正常考试。 下面分别介绍PMP英文报名和PMP考试中文报…...

PHP中使用ElasticSearch

PHP中使用ElasticSearch 使用cURL尝试ElasticSearch查看es基本信息列出所有的Index列举每个Index下的Type添加Index删除Index安装中文分词插件ik (安装完需要重启es)创建一个Index,并设置其结构和分词向Index增加记录POST方式(POST方式不需要传id,id随机生成)查看指定条目…...

Spring企业级程序设计 • 【第6章 深入Spring MVC开发】

全部章节 >>>> 本章目录 6.1 模型数据解析及控制器返回值 6.1.1 ModelAndView多种用法 6.1.2 Map添加模型数据和返回String类型值 6.1.3 Model添加模型数据和返回String类型值 6.1.4 返回值为String类型的重定向和转发 6.1.5 实践练习 6.2 Spring MVC表…...

投资理财1

1. 投资术语 熔断&#xff1a;也叫自动停盘机制&#xff0c;是指当股指波幅达到规定的熔断点时&#xff0c;交易所为控制风险采取的暂停交易措施。具体说是对某一合约在达到涨跌停板之前&#xff0c;设置一个熔断价格&#xff0c;使合约买卖报价在一段时间内只能在这一价格范围…...

CocosCreator开源框架(不断更新)

关于框架 最近项目里面需要搭建一个基础框架&#xff0c;所以我就参考了github&#xff0c;gitee上面的一些大佬的开源框架&#xff0c;这里也进行一个汇总&#xff0c;方便大家参考和学习。 关于编辑器版本&#xff0c;我觉得学习的时候不管是什么版本开发的框架&#xff0c…...

你不得不知道的36条社会潜规则(摘抄)

人过三十&#xff0c;你不得不知道的36条社会潜规则。   1、去别人家里串门记得一定要带点东西&#xff0c;即使你们关系再好&#xff0c;也要拿点礼品。   2、在别人面前一定要学会适当的装穷&#xff0c;即使你再有钱&#xff0c;也不要在朋友面前显摆。   3、警惕在你…...

macOS 使用技巧

快捷键 截图 获取文件地址 command option C 常用的系统快捷键 commandM:缩小窗口&#xff1b; commandW:关闭窗口&#xff1b; control单击&#xff1a;鼠标右键&#xff1b; command&#xff0b;H&#xff1a;隐藏窗口&#xff1b; commandQ:退出应用程序&#xff1…...

可持久化线段树 主席树 详解

&#x1f60a; | Powered By HeartFireY | Persistent Segment Tree &#x1f4d5; | 需要的前导知识&#xff1a;线段树(Segment Tree)、权值线段树、可持久化数据结构理论(Persistent Data Structure Theory) 一、可持久化线段树 简介 可持久化线段树&#xff0c;顾名思义…...

【每日一题】day29_01 正数数组的最小不可组成和

学习目标&#xff1a; 目标&#xff1a;熟练运用Java所学知识 学习内容&#xff1a; 本文内容&#xff1a;使用java解决 正数数组的最小不可组成和 文章目录学习目标&#xff1a;学习内容&#xff1a;题目描述解题思路&#xff1a;实现代码题目描述 链接&#xff1a;https:/…...

SpringBoot入门及官网教程

文章目录http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/https://spring.io/projects/spring-boothttps://springboot.io/http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/ https://spring.io/projects/spring-boot https://springboot.io/...

Python入门及官网教程

文章目录https://www.python.org/http://www.python-china.com/https://www.python.org/ http://www.python-china.com/...

源码部署pxc集群

想了想还是研究一下怎么源码安装pxc吧&#xff0c;毕竟很多组件都是源码安装的。 环境&#xff1a; yum install -y boost-devel libodb-boost-devel check-devel openssl-devel libaio-devel 安装scons 需要2.7 的Python wget https://nchc.dl.sourceforge.net/project/s…...

【阿里巴巴Java编程规范学习 四】Java质量安全规约

Java质量安全规约来源于规范里的单元测试和安全规约两部分&#xff0c;这两部分一直没有得到应有的重视&#xff0c;尤其感觉单元测试越来越被忽视&#xff08;因为直接通过Web请求测试貌似更加方便&#xff09;&#xff0c;但为了让代码健壮性更强&#xff0c;还是需要有的&am…...

世界各国简称 电话区号JSON数据

{"list": [{"city": "中国大陆","code": "86"},{"city": "中国香港","code": "852"},{"city": "中国澳门","code": "853"},{"city&…...

崩坏3区号+86_86,中国大陆国际区号是“ +86”,还是“ +086”、“ +0086”

中国大陆国际区号是“ 86”&#xff0c;还是“ 086”、“ 0086”中国大陆国际区号是“ 86”00是国内自己的国际拨号代码&#xff0c;不同国家的数字是不同的&#xff0c;也就是说中国打国外才用00加区号&#xff0c;国外打中国则要用当地代码加86。因为很不方便&#xff0c;所以…...

html如何嵌入手机,手机嵌入页面

游戏简介创世神创造了我们生活的大陆&#xff0c;人类&#xff0c;精灵&#xff0c;矮人&#xff0c;龙&#xff0c;兽人&#xff0c;各种生物在大陆生存着&#xff0c;与恶劣的自然环境斗争着。渐渐的各自的种族开始形成了各自的联盟与部落&#xff0c;为了争夺更多的生存资源…...

MagicDraw 18.5 SP4

2692407267qq.com&#xff0c;更多内容请见http://user.qzone.qq.com/2692407267/ MagicDraw 18.5 SP4...

magicdraw 2022x

2692407267qq.com&#xff0c;更多内容请见http://user.qzone.qq.com/2692407267/ magicdraw 2022x...

安装magicdrawUML出现的问题

1、出现the program can not handle XXXX问题是因为你的安装目录包含的中文文件夹。要每一级目录都是英文的才可以。或者&#xff0c;可以使用默认的安装目录&#xff0c;也是全英文的。 2、无法导入key,没有select license key files导入按钮 原因&#xff1a;这个一个坑&…...

MagicDraw建模显示中文问题

选择主菜单栏的“Options”->“Project”&#xff0c;打开“Project Options”属性窗体&#xff0c;单击左侧Frame的“Symbols properties styles”下的“Default&#xff08;Default&#xff09;”&#xff0c;右侧Frame中的“Font”项&#xff0c;默认值为“Arial"。…...

华为云桌面Workspace,让你的办公更加舒适惬意

在各行各业转型的过程中&#xff0c;企业对于线上办公的需求不断增多&#xff0c;越来越需要一个云办公平台&#xff0c;为企业更好实现数字化网络化办公降本增效。正逢佳节之际&#xff0c;在此为各大企业推荐一个高效的办公神器——华为云桌面Workspace。相信作为企业决策者的…...

AndroMDA中的用例图和活动图介绍(MagicDraw)

翻译了AndroMDA3.2使用手册 用例图&#xff08;Use-Cases&#xff09;用例代表一组逻辑处理&#xff0c;用例名字不能相同。用例的版型是<<FrontEndUseCase>>。应用入口的用例的版型是<<FrontEndApplication>>&#xff0c;有且仅有一个用例是这个版型。…...

支持团队开发的UML建模和CASE工具MagicDraw

Java建模软件MagicDraw的服务器软件。Teamwork Server允许多个用户同时使用相同的OO模型。UML模型存放在服务器上&#xff0c;每一个使用MagicDraw标准版、专业版或企业版的开发者都能各自锁定并处理模型的一个部分。对该部分所做的修改可提交到服务器与团队共享。服务器的工作…...

magicdraw 15 破解

magicdraw 15 破解...

MagicDraw UML 16.8 安装教程(2)-破解补丁

上一篇说了安装 教程&#xff0c;这个不破解时无法使用的 1.下载 破解补丁 地址:google MagicDraw UML 16.8 破解 很多 CSDN中的一个地址&#xff1a;http://download.csdn.net/source/2383166 2.解压rar文件 打开 Readme.txt 文件里面有详细的步骤&#xff1a;English is good…...

莫名其妙的解决了MagicDraw中文问题

今天试用MagicDraw16&#xff0c;虽然前面不太顺利&#xff0c;但还是正常的用起来了&#xff01; 先装的是16.6版本&#xff0c;但是网上没有找到破解&#xff0c;最后装16.0能正常应用。 再就是遇到了支持中文的问题。树状目录里的组件的名称全部是小方格&#xff01; 在网上…...

解决magicdraw16.8无法在win8.1下破解使用

1、magicdraw16.8 在win7下安装后&#xff0c;破解成功后&#xff0c;正常启动一次。 2、将生成的.magicdraw文件夹(一般在用户的目录下)拷贝到win8.1的下面&#xff0c;覆盖现有的文件即可。...

MagicDraw UML 16.8 安装教程

1&#xff0c;下载程序 程序下载地址&#xff1a;http://www.newhua.com/soft/103340.htm(华军) http://xiazai.zol.com.cn/detail/41/405156.shtml(ZOL) 2.安装程序 双击 安装程序“MD_UML_168_win.exe” MagicDraw UML是捆绑JVM版本1.6.0_18。大多数的测试程序和调试这个JVM的…...

UML工具 MAGICDraw

今天启动UML工具 MAGICDraw时&#xff0c;提示一个对话框&#xff1a;Java Virtual Machine Launcher Could not find the main class,Program will exit .因为用的是破解版&#xff0c;我以为是破解版变坏了。后来跟BGY要了一个软件&#xff0c;也提示同样错误&#xff0c;上…...

MagicDraw

MagicDraw很强大&#xff0c;视频http://www.magicdraw.com/online_demo 至少要求设计用例图、类图、活动图...

MagicDraw-状态机图

什么是状态机图 状态机图是能够用于说明系统动态行为信息的三种SysML 图中的最后一种。你可以在状态机图上显示各种各样的状态&#xff0c;并且可以指定四种类型的事件&#xff0c;从而在运行的系统中触发那些状态之间的转换。Sys ML 还可以使用正交区域对基于状态的并发行为建…...

MagicDraw-IBD图

文章目录IBD的目的IBD外框IBD组成部分属性引用属性连接器项目流内嵌组成部分和引用点标识法连接内嵌属性IBD的目的 IBD 是为了指定单个模块的内部结构。 IBD 是系统或者系统一个组成部分的静态&#xff08;结构化&#xff09;视图。 IBD 可以表达在BDD 中无法表达的信息&…...