新搭了一个项目在测试时报了一个错误:
com.ibatis.sqlmap.client.SqlMapException: There is no statement named findUserByMap in this SqlMap.
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.getMappedStatement(SqlMapExecutorDelegate.java:231)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.getMappedStatement(SqlMapClientImpl.java:201)
根据错误定位到代码是发生在下面的方法中:
public MappedStatement getMappedStatement(String id)
/* */ {
/* 229 */ MappedStatement ms = (MappedStatement)this.mappedStatements.get(id);
/* 230 */ if (ms == null) {
/* 231 */ throw new SqlMapException("There is no statement named " + id + " in this SqlMap.");
/* */ }
/* 233 */ return ms;
/* */ }
说明mappedStatements.get(id)调用结果为空,说明查询调的sql配置的xml中语句id未空,也就是说没有ibatis没有加载我的配置文件,这么一来问题就很明显了,是我的ibatis配置有问题。ibatis配置如下:
<bean id="sqlSessionFactory" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<!-- 手动引入mapping.xml文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
这才发现,配置ibatis时只配置了扫描一个xml,这里需要加上扫描通配符匹配到的目录下的xml。另外测试发现必须要配置一个configLocation,否则会报错,现在ibatis配置如下:
<bean id="sqlSessionFactory" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<!-- 手动引入mapping.xml文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 自动扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath:com/test/**/sql-*.xml"></property>
</bean>
重启报错如下:
2018-05-31 19:35:10,250 WARN [org.springframework.web.context.support.XmlWebApplicationContext] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testsqlaction': Unsatisfied dependency expressed through field 'testSqlService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testSqlService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testSqlDao': Unsatisfied dependency expressed through field 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [spring/spring-mybatis.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'mapperLocations' of bean class [org.springframework.orm.ibatis.SqlMapClientFactoryBean]: Bean property 'mapperLocations' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
2018-05-31 19:35:10,256 ERROR [org.springframework.web.context.ContextLoader] - Context initialization failed
从报错可以看出是ibatis配置无法识别属性mapperLocaltions,查看SqlMapClientFactoryBean的源码发现,ibatis映射xml是使用的mappingLocations:
/**
* Set locations of iBATIS sql-map mapping files that are going to be
* merged into the SqlMapClient configuration at runtime.
* <p>This is an alternative to specifying "<sqlMap>" entries
* in a sql-map-client config file. This property being based on Spring's
* resource abstraction also allows for specifying resource patterns here:
* e.g. "/myApp/*-map.xml".
* <p>Note that this feature requires iBATIS 2.3.2; it will not work
* with any previous iBATIS version.
*/
public void setMappingLocations(Resource[] mappingLocations)
{
this.mappingLocations = mappingLocations;
}
并且从源码注释也可以看出是从2.3.2版本开始生效,之前版本是无效的。这就和MyBatis有点区别了,Mybatis配置如下:
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="SqlMapClient" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath:com/test/mapping/*.xml"></property>
</bean>
Mybatis使用的才是mapperLocations。