項目是SpringBoot + Mybatis建構的。關鍵元件版本如下:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.0.2</version>
</dependency>
下面給出關鍵代碼:
@SpringBootApplication
@ServletComponentScan
@EnableCaching
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) throws IOException {
SpringApplication.run(Application.class, args);
}
}
@Configuration
@AutoConfigureAfter(MyBatisConfig.class)
public class MyBatisMapperScannerConfig {
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage("com.xxx.retailOrder.mapper");// mapper package namespace
return mapperScannerConfigurer;
}
}
@RequestMapping(value = "/xxxOrderSignatureReceived", produces = APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseDTO<?> orderSignatureReceived(@Valid @RequestBody RetailOrderReceived2DTO dto){
myRetailOrderService.orderReceipt(dto);
return onSuccess(null);
}
控制台此時會報出這樣的錯誤:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.retailorder.service.MyRetailOrderService.orderReceipt
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:196) ~[mybatis-3.3.1.jar:3.3.1]
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:44) ~[mybatis-3.3.1.jar:3.3.1]
at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:59) ~[mybatis-3.3.1.jar:3.3.1]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52) ~[mybatis-3.3.1.jar:3.3.1]
注:根據經驗,先要排除Mybatis配置等相關錯誤原因
根據上面日志,不難想像:在控制層注入MyRetailOrderService對象時,使用注解@Autowired注入時,從Mybatis相關類中拿到了CGLIB方式生成的對象,而不是我容器本身業務對象。也就是說,我的業務層對象被代理生成了Mybatis用的Mapper類代理對象。這不是正常操作,這個事情springboot什麼時候做的呢?
本人對SpringBoot不太了解。查閱相關資料,說是根據依賴包會進行相關自動配置。有了這個理論前提,我用方法一:禁止SpringBoot對Mybatis自動配置。
@SpringBootApplication(exclude = MybatisAutoConfiguration.class)
@ServletComponentScan
@EnableCaching
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) throws IOException {
SpringApplication.run(Application.class, args);
}
}
方法二:強行用MapperScan指定掃描範圍
@Configuration
@AutoConfigureAfter(MyBatisConfig.class)
@MapperScan(basePackages = "com.xxx.retailorder.mapper")
public class MyBatisMapperScannerConfig {
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage("com.xxx.retailorder.mapper");// mapper package namespace,此處指定不起作用
return mapperScannerConfigurer;
}
}
對于方法二不明白的地方是,為什麼mapperScannerConfiguer設定掃描範圍不起作用,非要用MapperScan注解才起作用。有路過的大神指教一下嗎?