使用mybatis 3.2.8,Spring 3.2.9发布,mybatis-spring 1.2.2配置我的项目的DAO和项目需要方便mysql和oracle,所以我使用了databaseIdProvider来适应这里多数据源是我的配置:MyBatis多数据源配置问题
- 数据源
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>xxxxx</value>
</property>
</bean>
- vendorProperties
- databaseIdProvider
- 的SqlSessionFactory
- 我的本地环境是Oracle,所以我修改了映射。XML,删除了MySQL配置刚刚离开了Oracle配置:
- 的话,我想也许MyBatis的不认可我的运行环境,所以我看着源代码,找出信息是否被设置到MyBatis的或没有。我发现启动类
org.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory()
方法有: - 然后,我开始发现何时何地sqlFragments被分配value.i发现sqlFragments解析mapper.xml时被分配:
org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement()
<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>
<bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
<property name="properties" ref="vendorProperties" />
</bean>
<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'的值。 ,所以我下面的步骤打击找到什么是错的:
<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>
但它也不能正常工作,例外仍然存在。
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在这里,并找到价值是正确的。
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操作之前。 现在我不知道如何解决这个问题。是否有人遇到像我一样的情况?
你确定所有的命名空间都正确吗?声明PagePrefix的片段的名称空间是什么?当你引用在antoher文件中定义的片段时,引用的ID必须提前包含名称空间 – Giovanni 2015-03-19 07:35:37
tks,我删除了sql标记的databaseId属性,并且它根本不会引发异常,所以命名空间是正确的。 – Gospel 2015-03-19 07:42:14