MyBatis多数据源配置问题

时间:2015-03-19 07:22:12

标签: java spring mybatis

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

  1. 数据源
  2. 
    
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
      <property name="jndiName">
        <value>xxxxx</value>
      </property>
    </bean>
    &#13;
    &#13;
    &#13;

    1. vendorProperties
    2. &#13;
      &#13;
      <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>
      &#13;
      &#13;
      &#13;

      1. databaseIdProvider
      2. &#13;
        &#13;
        <bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
          <property name="properties" ref="vendorProperties" />
        </bean>
        &#13;
        &#13;
        &#13;

        1. 的SqlSessionFactory
        2. &#13;
          &#13;
          <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>
          &#13;
          &#13;
          &#13;

          因为mysql的分页与oracle不同,所以我写了两种分页方式,并依赖于运行时环境来选择使用哪一个。mapper.xml就是这样的:

          &#13;
          &#13;
          <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>
          &#13;
          &#13;
          &#13;

          并像这样使用它:

          &#13;
          &#13;
          <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>
          &#13;
          &#13;
          &#13;

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

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

          我发现这个异常是由org.apache.ibatis.session引起的.Configuration.sqlFragments没有密钥是&#39; PagePrefix&#39;的值。 所以我按照打击步骤找出错误:

          1. 我的本地环境是oracle,所以我修改了mapper.xml,删除了刚刚离开oracle config的mysql配置:
          2. &#13;
            &#13;
            <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>
            &#13;
            &#13;
            &#13;

            但它也不起作用,例外仍然存在。

            1. 然后我想也许mybatis没有识别我的运行时环境,所以我查看了源代码,找出信息是否已设置到mybatis中。我找到了启动类{{1} }方法有:
            2. &#13;
              &#13;
              org.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory()
              &#13;
              &#13;
              &#13;

              和我在这里切换断点并找到正确的值。

              1. 然后我开始找到分配sqlFragments的位置和时间。我发现在解析mapper.xml时分配了sqlFragments: if (this.databaseIdProvider != null) { try { configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource)); } catch (SQLException e) { throw new NestedIOException("Failed getting a databaseId", e); } }
              2. &#13;
                &#13;
                org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement()
                &#13;
                &#13;
                &#13;

                ,方法 private void configurationElement(XNode context) { try { String namespace = context.getStringAttribute("namespace"); if (namespace.equals("")) { 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); } }在sqlFragments上执行实际的赋值,并根据databaseId查找标记&#39;

                &#13;
                &#13;
                sqlElement
                &#13;
                &#13;
                &#13;

                但是在那个时候还没有设置databaseId,因为解析阶段在我之前提到的setDatabaseId操作之前。 现在我不知道如何解决这个问题。任何人都遇到过和我一样的情况吗?

2 个答案:

答案 0 :(得分: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>

PostgresSQL是

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

在我有的映射文件中

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

并且它已正确加载

答案 1 :(得分:0)

我发现问题导致我在mybatis-config.xml中编写了mappers标记,以便mybatis可以自己进行配置,尽管是Spring的configure.so如果你想通过Spring使用多数据源,那你就不能写mybatis'自己的config xml。