2015-03-19 70 views
0

使用mybatis 3.2.8,Spring 3.2.9发布,mybatis-spring 1.2.2配置我的项目的DAO和项目需要方便mysql和oracle,所以我使用了databaseIdProvider来适应这里多数据源是我的配置:MyBatis多数据源配置问题

  1. 数据源

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
 
    <property name="jndiName"> 
 
    <value>xxxxx</value> 
 
    </property> 
 
</bean>

  • vendorProperties
  • <bean id="vendorProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
     
        <property name="properties"> 
     
        <props> 
     
         <prop key="SQL Server">sqlserver</prop> 
     
         <prop key="DB2">db2</prop> 
     
         <prop key="Oracle">oracle</prop> 
     
         <prop key="MySQL">mysql</prop> 
     
         <prop key="H2">h2</prop> 
     
        </props> 
     
        </property> 
     
    </bean>

  • databaseIdProvider
  • <bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider"> 
     
        <property name="properties" ref="vendorProperties" /> 
     
    </bean>

  • 的SqlSessionFactory
  • <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
     
        <property name="dataSource" ref="dataSource" /> 
     
        <property name="databaseIdProvider" ref="databaseIdProvider" /> 
     
        <property name="configLocation" value="classpath:mybatis-config.xml"></property> 
     
    </bean>

    因为MySQL的寻呼是从Oracle的如此不同我写寻呼的两种方法,并且取决于运行时环境选择使用which.here是mapper.xml:

    <sql databaseId="oracle" id="PagePrefix"> 
     
        <!-- 
     
          WARNING - @mbggenerated 
     
          This element is automatically generated by MyBatis Generator, do not modify. 
     
         --> 
     
        <if test="page != null"> 
     
        select * from (select row_.*, rownum rownum_ from (
     
        </if> 
     
    </sql> 
     
    <sql databaseId="mysql" id="PagePrefix"> 
     
        <!-- 
     
          WARNING - @mbggenerated 
     
          This element is automatically generated by MyBatis Generator, do not modify. 
     
         --> 
     
        <if test="page != null"> 
     
        select * from (
     
        </if> 
     
    </sql>

    和使用它像这样:上述

    <select id="selectByExample" parameterType="xxx.xxx.xxx" resultMap="BaseResultMap"> 
     
        <!-- 
     
          WARNING - @mbggenerated 
     
          This element is automatically generated by MyBatis Generator, do not modify. 
     
         --> 
     
        <include refid="PagePrefix" />select 
     
        <if test="distinct"> 
     
        distinct 
     
        </if> 
     
        from xxx 
     
        <if test="_parameter != null"> 
     
        <include refid="Example_Where_Clause" /> 
     
        </if> 
     
        <include refid="PageSuffix" /> 
     
    </select>

    是我的所有配置。 当我运行的查询操作或任何其他DML,控制台会打印:

    org.apache.ibatis.builder.IncompleteElementException: Could not find SQL statement to include with refid 'xxx.xxx.xxx.PagePrefix'

    我发现这个异常是由org.apache.ibatis.session.Configuration引起的。 sqlFragments没有键值为'PagePrefix'的值。 ,所以我下面的步骤打击找到什么是错的:

    1. 我的本地环境是Oracle,所以我修改了映射。XML,删除了MySQL配置刚刚离开了Oracle配置:

    <sql databaseId="oracle" id="PagePrefix"> 
     
        <!-- 
     
           WARNING - @mbggenerated 
     
           This element is automatically generated by MyBatis Generator, do not modify. 
     
          --> 
     
        <if test="page != null"> 
     
        select * from (select row_.*, rownum rownum_ from (
     
        </if> 
     
    </sql>

    但它也不能正常工作,例外仍然存在。

  • 的话,我想也许MyBatis的不认可我的运行环境,所以我看着源代码,找出信息是否被设置到MyBatis的或没有。我发现启动类org.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory()方法有:
  • if (this.databaseIdProvider != null) { 
     
          try { 
     
          configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource)); 
     
          } catch (SQLException e) { 
     
          throw new NestedIOException("Failed getting a databaseId", e); 
     
          } 
     
         }

    和我切换BR eakpoint在这里,并找到价值是正确的。

  • 然后,我开始发现何时何地sqlFragments被分配value.i发现sqlFragments解析mapper.xml时被分配:org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement()
  •  private void configurationElement(XNode context) { 
     
         try { 
     
          String namespace = context.getStringAttribute("namespace"); 
     
          if (namespace.equals("")) { 
     
         \t throw new BuilderException("Mapper's namespace cannot be empty"); 
     
          } 
     
          builderAssistant.setCurrentNamespace(namespace); 
     
          cacheRefElement(context.evalNode("cache-ref")); 
     
          cacheElement(context.evalNode("cache")); 
     
          parameterMapElement(context.evalNodes("/mapper/parameterMap")); 
     
          resultMapElements(context.evalNodes("/mapper/resultMap")); 
     
          sqlElement(context.evalNodes("/mapper/sql")); 
     
          buildStatementFromContext(context.evalNodes("select|insert|update|delete")); 
     
         } catch (Exception e) { 
     
          throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e); 
     
         } 
     
         }

    和方法sqlElement做sqlFragments和ACC实际分配值奥尔丁的databaseId找到标签'

    private void sqlElement(List<XNode> list, String requiredDatabaseId) throws Exception { 
     
         for (XNode context : list) { 
     
          String databaseId = context.getStringAttribute("databaseId"); 
     
          String id = context.getStringAttribute("id"); 
     
          id = builderAssistant.applyCurrentNamespace(id, false); 
     
          if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) sqlFragments.put(id, context); 
     
         } 
     
         }

    但在那个时候databaseId还尚未设置怎么一回事,因为解析阶段就是我前面提到的setDatabaseId操作之前。 现在我不知道如何解决这个问题。是否有人遇到像我一样的情况?

    +0

    你确定所有的命名空间都正确吗?声明PagePrefix的片段的名称空间是什么?当你引用在antoher文件中定义的片段时,引用的ID必须提前包含名称空间 – Giovanni 2015-03-19 07:35:37

    +0

    tks,我删除了sql标记的databaseId属性,并且它根本不会引发异常,所以命名空间是正确的。 – Gospel 2015-03-19 07:42:14

    回答

    0

    我发现问题是由于我在mybatis-config中写了mappers标记。xml,以便mybatis能够完成自己的配置,尽管Spring的configure.so如果你想通过Spring使用多数据源,你不能写mybatis自己的配置xml。

    1

    我设法创建了一个工作示例。诀窍是获得属性的正确映射。你必须能够指定哪些

    DataSource().getConnection().getMetaData().getDatabaseProductName() 
    

    回报和用户它作为你的财产文件的密钥 我对Postgres的映射是

    <bean id="vendorProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
        <property name="properties"> 
         <props> 
          <prop key="PostgreSQL">postgres</prop> 
          <prop key="Oracle">oracle</prop> 
         </props> 
        </property> 
    </bean> 
    

    PostgreSQL的是

    DataSource().getConnection().getMetaData().getDatabaseProductName() 
    
    结果

    在映射文件中我有

    <sql databaseId="postgres" id="PagePrefix"> 
        select sum(a) from (
    </sql> 
    

    它正确加载了

    +0

    谢谢乔瓦尼,我发现了这个问题。 – Gospel 2015-03-19 10:30:24