Configuration--databaseIdProvider(三-6)

本文深入探讨了MyBatis的databaseIdProvider标签,解释了其如何根据数据库厂商执行特定语句。通过设置databaseId,MyBatis加载对应数据库的映射语句。内容包括使用示例、属性别名的设置,以及解析代码分析,重点关注了VendorDatabaseIdProvider类的getDatabaseId方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章我们来分析一下databaseIdProvider标签.

mybatis可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的databaseId属性.mybatis会加载不带databaseId属性和带有匹配当前数据库databaseId属性的所有语句.如果同时找到带有databaseId和不带databaseId的相同语句,则后者会被舍弃.

用法为:

<databaseIdProvider type="DB_VENDOR" />

这里的DB_VENDOR会通过DatabaseMetaDatagetDatabaseProductName()方法返回的字符串进行设置databaseId. 由于通常情况下这个字符串都非常长而且相同产品的不同版本会返回不同的值,所以最好通过设置属性别名来使其变短,如下:

<databaseIdProvider type="DB_VENDOR">
  <property name="SQL Server" value="sqlserver"/>
  <property name="DB2" value="db2"/>        
  <property name="Oracle" value="oracle" />
</databaseIdProvider>

我们来看一下解析该标签的代码,databaseIdProviderElement(root.evalNode(“databaseIdProvider”))方法:

  private void databaseIdProviderElement(XNode context) throws Exception {
    DatabaseIdProvider databaseIdProvider = null;
    if (context != null) {
      String type = context.getStringAttribute("type");
      // 从这里可以看出,指定为VENDOR,也会被当作DB_VENDOR
      if ("VENDOR".equals(type)) type = "DB_VENDOR"; 
      Properties properties = context.getChildrenAsProperties();
      // 实例化别名为type的DatabaseIdProvider(内置的为DB_VENDOR)
      databaseIdProvider = (DatabaseIdProvider) resolveClass(type).newInstance();
      databaseIdProvider.setProperties(properties);
    }
    Environment environment = configuration.getEnvironment();
    if (environment != null && databaseIdProvider != null) {
      // 通过DataSource,获取databaseId
      String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());
      // 将databaseId设置进Configuration中
      configuration.setDatabaseId(databaseId);
    }
  }

从上述代码我们可以看出,获取databaseId主要还是要看DatabaseIdProvidergetDatabaseId方法,当然我们可以自定义DatabaseIdProvider,但是本篇文章,我们先来了解mybatis内置的DatabaseIdProvider.

首先,我们在Configuration的构造函数中,找到DB_VENDOR别名对应的VendorDatabaseIdProvider:

typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);

接着我们来看VendorDatabaseIdProvidergetDatabaseId方法:

  public String getDatabaseId(DataSource dataSource) {
    if (dataSource == null) throw new NullPointerException("dataSource cannot be null");
    try {
      // 调用getDatabaseName方法
      return getDatabaseName(dataSource);
    } catch (Exception e) {
      log.error("Could not get a databaseId from dataSource", e);
    }
    return null;
  }

  private String getDatabaseName(DataSource dataSource) throws SQLException {
    // 获取数据库名称
    String productName = getDatabaseProductName(dataSource);
    if (this.properties != null) {
      // 通过之前在databaseIdProvider子标签property中设置的key,value值,返回一个我们定义的比较简单的名称作为databaseId,这样我们在设置映射语句的databaseId属性时,也能使用这个简短的名称,而不是使用复杂并且可能还带有版本号的数据库名称
      for (Map.Entry<Object, Object> property : properties.entrySet()) {
        // 如果productName为"Oracle (DataDirect)",根据之前的设置,将会返回"oracle"
        if (productName.contains((String) property.getKey())) {
          return (String) property.getValue();
        }
      }
      return null;
    }
    return productName;
  }

  // 该方法通过DatabaseMetaData获取数据库的名称
  private String getDatabaseProductName(DataSource dataSource) throws SQLException {
    Connection con = null;
    try {
      con = dataSource.getConnection();
      DatabaseMetaData metaData = con.getMetaData();
      return metaData.getDatabaseProductName();
    } finally {
      if (con != null) {
        try {
          con.close();
        } catch (SQLException e) {
          // ignored
        }
      }
    }
  }

综上,databaseIdProvider标签我们就讲完啦.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值