1. 程式人生 > >關於Service方法呼叫時出現org.apache.ibatis.binding.BindingException錯誤的可能原因

關於Service方法呼叫時出現org.apache.ibatis.binding.BindingException錯誤的可能原因

專案是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註解才起作用。有路過的大神指教一下嗎?