`
topcat
  • 浏览: 284457 次
  • 性别: Icon_minigender_1
  • 来自: 湖北武汉
社区版块
存档分类
最新评论

mybatis支持多数据库切换

阅读更多

问题:


使用mybatis时都是用的sqlmapper来做的数据库到java对象的映射,因此在针对一些特定数据库方言使用时无法在多个数据库上切换。

解决方案:


  • mybatis篇

思路:

通过定义environment的id来指定使用不同的数据库映射文件,如下
<!--WizRtf2Html Charset=0 -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="pwd" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="cn/dcr/mybatis/entity/UserMapper.xml" />
</mappers>
</configuration>
environment的id是mysql映射文件是cn/dcr/mybatis/entity/UserMapper.xml
那么mybatis实际是读取的mysql/cn/dcr/mybatis/entity/UserMapper.xml

实现:

以org.apache.ibatis.builder.xml.XMLConfigBuilder类为蓝本创建一个新类org.apache.ibatis.builder.xml.XMLConfigBuilderEx
添加一个成员变量
private String dialect;
修改environmentsElement方法设置方言
private void environmentsElement(XNode context) throws Exception {
if (context != null) {
if (environment == null) {
environment = context.getStringAttribute("default");
}
for (XNode child : context.getChildren()) {
String id = child.getStringAttribute("id");
dialect = id.toLowerCase();//设置方言
if (isSpecifiedEnvironment(id)) {
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
Environment.Builder environmentBuilder = new Environment.Builder(id).transactionFactory(txFactory).dataSource(dsFactory.getDataSource());
configuration.setEnvironment(environmentBuilder.build());
}
}
}
}
修改mapperElement方法
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
InputStream inputStream;
if (resource != null && url == null) {
if(dialect != null){
resource = dialect + "/" + resource;//从方言指定位置查找
}
ErrorContext.instance().resource(resource);
inputStream = Resources.getResourceAsStream(resource);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
} else if (url != null && resource == null) {
if(dialect != null){
url = dialect + "/" + url;//从方言指定位置查找
}
ErrorContext.instance().resource(url);
inputStream = Resources.getUrlAsStream(url);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
} else {
throw new BuilderException("A mapper element may only specify a url or resource, but not both.");
}
}
}
}
继承org.apache.ibatis.session.SqlSessionFactoryBuilder类创建一个新类org.apache.ibatis.session.SqlSessionFactoryBuilderEx用来加载org.apache.ibatis.builder.xml.XMLConfigBuilderEx
覆盖父类中的build方法
public SqlSessionFactory build(InputStream inputStream, String environment, Properties props) {
try {
XMLConfigBuilderEx parser = new XMLConfigBuilderEx(inputStream, environment, props);
Configuration config = parser.parse();
return build(config);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
调用org.apache.ibatis.builder.xml.XMLConfigBuilderEx来加载配置文件
  • spring篇

思路:

自定义mybatis配置加载Bean在spring的配置文件中添加方言的配置让自定义Bean在加载mybatis的配置时可以使用不同的数据库映射文件,如下
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBeanEx">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:configuration.xml" />
<property name="mapperLocations" value="classpath*:${jdbc.dialect}/mappers/*.xml" />
</bean>
${jdbc.dialect}在配置文件中设置,如mysql,那么spring会把mysql/mappers下的所有映射文件加载进来

实现:

以org.mybatis.spring.SqlSessionFactoryBean为蓝本创建org.mybatis.spring.SqlSessionFactoryBeanEx类
将成员变量
private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
修改为
private SqlSessionFactoryBuilderEx sqlSessionFactoryBuilderEx = new SqlSessionFactoryBuilderEx();
并去掉setSqlSessionFactoryBuilder方法添加setSqlSessionFactoryBuilderEx方法
覆盖buildSqlSessionFactory方法
protected SqlSessionFactory buildSqlSessionFactory() throws IOException, IllegalAccessException, InstantiationException {

XMLConfigBuilderEx xmlConfigBuilderEx;
Configuration configuration;

if (this.configLocation != null) {
try {
xmlConfigBuilderEx = new XMLConfigBuilderEx(this.configLocation.getInputStream(), null, this.configurationProperties);
configuration = xmlConfigBuilderEx.parse();
} catch (Exception ex) {
throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
} finally {
ErrorContext.instance().reset();
}

if (this.logger.isDebugEnabled()) {
this.logger.debug("Parsed configuration file: '" + this.configLocation + "'");
}
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
}
configuration = new Configuration();
}

if (this.transactionFactory == null) {
this.transactionFactory = new SpringManagedTransactionFactory(this.dataSource);
}

Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);

configuration.setEnvironment(environment);

if (!ObjectUtils.isEmpty(this.mapperLocations)) {
Map<String, XNode> sqlFragments = new HashMap<String, XNode>();

for (Resource mapperLocation : this.mapperLocations) {
if (mapperLocation == null) {
continue;
}

// MyBatis holds a Map using "resource" name as a key.
// If a mapper file is loaded, it searches for a mapper
// interface type.
// If the type is found then it tries to load the mapper file
// again looking for this:
//
// String xmlResource = type.getName().replace('.', '/') +
// ".xml";
//
// So if a mapper interface exists, resource cannot be an
// absolute path.
// Otherwise MyBatis will throw an exception because
// it will load both a mapper interface and the mapper xml file,
// and throw an exception telling that a mapperStatement cannot
// be loaded twice.
String path;
if (mapperLocation instanceof ClassPathResource) {
path = ((ClassPathResource) mapperLocation).getPath();
} else {
// this won't work if there is also a mapper interface in
// classpath
path = mapperLocation.toString();
}

try {
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, path, sqlFragments);
xmlMapperBuilder.parse();
} catch (Exception e) {
throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
}

if (this.logger.isDebugEnabled()) {
this.logger.debug("Parsed mapper file: '" + mapperLocation + "'");
}
}
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Property 'mapperLocations' was not specified, only MyBatis mapper files specified in the config xml were loaded");
}
}

return this.sqlSessionFactoryBuilderEx.build(configuration);
}
0
6
分享到:
评论

相关推荐

    Mybatis的切换数据库

    此外,如果你的项目使用了Spring框架,那么可以利用Spring的多数据源支持与Mybatis结合,通过Spring的 `AbstractRoutingDataSource` 类来实现动态数据源切换。`AbstractRoutingDataSource` 可以根据某种策略(如 ...

    SpringBoot集成MyBatis-Plus实现国产数据库适配.docx

    MyBatis-Plus 支持的数据库包括: * MySQL * MariaDB * Oracle * DB2 * H2 * HSQL * SQLite * Postgre * SQLServer * Presto * Gauss * Firebird * Phoenix * ClickHouse * Sybase ASE * OceanBase * 达梦数据库 * ...

    spring+hibernate和spring+myBatis实现连接多个数据库,同时操作的项目

    "spring+hibernate和spring+myBatis实现连接多个数据库,同时操作的项目"是针对这种需求的一个解决方案,旨在提供一种灵活且动态的数据源切换机制。 首先,Spring框架作为Java领域中最受欢迎的应用框架之一,其强大...

    springmvc+mybatis实现动态切换数据库

    完整的Demo结合了springmvc——mybatis,实现了工具类文件上传下载,结合了Redis的初步使用,并且能使用threadlocal实现数据库动态切换,很适合初建项目做参考,适合初学者使用。

    mybatis+druid association 切换数据源

    在IT行业中,数据库连接管理是系统性能优化的关键环节之一,MyBatis作为一款优秀的持久层框架,配合Druid这样的高效数据库连接池,可以提供高效、稳定的数据库操作支持。本话题聚焦于"Mybatis+Druid Association ...

    SpringBoot整合mybatis-plus实现多数据源的动态切换且支持分页查询.pdf

    在SpringBoot项目中,整合Mybatis-Plus并实现多数据源的动态切换,同时支持分页查询是一项常见的需求。以下将详细阐述这个过程中的关键步骤和技术要点。 首先,我们需要引入必要的Maven依赖。这里提到了四个关键...

    使用springboot + JPA / MyBatis 实现多数据源动态切换

    在现代企业级应用开发...总的来说,Spring Boot结合JPA或MyBatis实现多数据源动态切换,不仅提高了系统的灵活性,还便于进行数据库扩展和管理。理解和掌握这一技术,对于提升系统设计能力和解决复杂问题具有重要意义。

    Springboot整合Druid与Mybatis的多数据源切换

    在现代企业级应用开发中,数据源管理是一个关键部分,特别是在多租户或者需要根据业务需求动态切换数据库的场景下。本教程将详细介绍如何在Spring Boot项目中整合Druid数据源池与Mybatis,实现多数据源切换的功能,...

    springboot2.0+mybatis主从数据库双数据源。

    主数据库用于处理写操作,从数据库用于处理读操作,这样可以将读压力分散到多个从库,提高系统整体性能。通常,主库的数据会实时同步到从库,确保数据一致性。主从复制的实现方式包括异步复制和半同步复制等,具体...

    SpringBoot+Mybatis实现数据源动态切换

    springboot实现数据源动态切换 注意事项: 1. 该demo采用yml配置数据库信息,注意url标签为jdbc-url 2.项目中加了日志输出,可看到完整执行过程 3.在Service中应用事务时,自定义的注解将失效,解决办法:可将注解...

    mybatis+spring实现动态切换数据源

    在企业级应用开发中,动态数据源是一种常见需求,它允许程序在运行时根据不同的业务逻辑切换到不同的数据库。在本项目中,我们将探讨如何利用MyBatis与Spring框架实现动态切换数据源的功能。首先,我们需要理解...

    Mybatis+Spring+SpringMVC+quartz多数据源切换

    这个项目结合了四个关键的技术组件,它们分别是Mybatis、Spring、SpringMVC和Quartz,下面将详细介绍这些技术以及它们在多数据源切换和跨数据库同步中的应用。 **Mybatis** 是一款轻量级的Java持久层框架,它允许...

    springboot+mybatis动态切换数据源完整项目架构

    本项目"springboot+mybatis动态切换数据源完整项目架构"正是针对这种需求提供的一种解决方案,它支持MySQL和Oracle数据库,使得开发者可以轻松地在两者之间进行数据源的切换,以适应不同的业务场景。 首先,我们要...

    spring mybatis 多数据源动态切换

    Spring 和 MyBatis 结合使用时,实现多数据源动态切换是一项重要的技术。本文将深入探讨如何在 Spring 中配置和管理多个数据源,并实现动态切换。 首先,我们需要理解“多数据源”是什么。它是指在一个应用中同时...

    mybatis自定义注解完成数据库切库

    然而,标准的MyBatis注解并不直接支持切换不同的数据库。为了实现数据库切库,我们需要创建一个自定义注解,用于标记需要切换数据库的方法,并编写相应的拦截器来处理这些注解。 1. **创建自定义注解**: 创建一个...

    对应的文章 Springboot Mybatis 多数据源利用注解动态切换数据库

    以上就是在Spring Boot中利用注解动态切换多数据源的基本步骤。这种设计使得我们的代码更加模块化,可以根据业务需求灵活地选择和切换数据源,提高了代码的可维护性和可扩展性。在实际项目中,还可以结合事务管理、...

    SpringBoot+gradle+mybatis多数据源动态配置

    综上所述,这个项目通过SpringBoot、Gradle和MyBatis,实现了一个支持多数据源动态切换的应用。开发者可以利用AOP在运行时根据业务逻辑选择合适的数据源,提高了系统的灵活性和可扩展性。同时,Gradle的使用使得依赖...

    Spring+SpringMvc+MybatisPlus+Aop(自定义注解)动态切换数据源

    MybatisPlus是在Mybatis基础上扩展的轻量级ORM(对象关系映射)框架,它简化了SQL查询和实体对象的绑定,使得开发者可以更专注于业务逻辑,而不用过多地关注数据库操作的细节。在这个项目中,MybatisPlus用于执行...

    mybatis-plus+动态数据源

    这种技术在分布式系统、微服务架构中非常常见,可以方便地支持多个数据库的切换,如读写分离、数据库分片等场景。 3. **自定义数据源配置**: 自定义数据源配置通常涉及到Spring框架中的`DataSource`接口实现,如...

    Mybatis 多数据源配置说明.docx

    对于存在主从关系的多数据源场景,通常需要实现数据源的动态切换,以便根据具体的业务逻辑来决定使用哪个数据库执行查询或更新操作。这种情况下,可以利用Spring的AOP功能来实现数据源的动态选择。 - **创建数据...

Global site tag (gtag.js) - Google Analytics