MyBatis-Spring-Boot
MyBatis-Spring-Boot copied to clipboard
大神帮忙看下-----只差把这个示例代码 全部copy过去了。
错误:Caused by: java.lang.InstantiationException: tk.mybatis.mapper.provider.SpecialProvider
at java.lang.Class.newInstance(Class.java:427)
at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:85)
... 136 common frames omitted
Caused by: java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.SpecialProvider.
相关代码已上传到github:https://github.com/helloworldtang/SpringBootCookbook rest接口:/tx/post 所在class: com.tangcheng.rest.TxController
重新切了个分支:v1.0.0_tx 去掉通用mapper,只使用mybatis-spring-boot-starter,就可以正常使用了
重新启了一个Module,按照例子中操作了一遍。是ok的 我上面的那个项目中,那个地方的配置干扰了通用Mapper的初始呢? 奇怪
上面错误的原因是mapper配置错误,导致通用方法没有被正确的初始化。
@abel533 反复把代码与这个例子比对了一下。没有发现错。跟了下代码,发现执行过程中传的参数都对
但还是报错了:
Error invoking SqlProvider method (tk.mybatis.mapper.provider.SpecialProvider.dynamicSQL). Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.SpecialProvider
报错位置:
[
有时间给看看呗,没有找到门道啊
示例代码在项目中的位置:
@abel533 原来是SpecialProvider.class.newInstance();报错了:
为什么呢?
今天在对比代码时发现一个: 上面报错项目中MappedStatement.java中sqlSource是tk.mybatis.mapper.provider.SpecialProvider 你给出的例子中却是org.apache.ibatis.scripting.xmltags.DynamicSqlSource
哪个地方的配置决定实例化哪个SqlSource呢?
有错的:
正常的:
@abel533 Mapper哪个地方配错了呢。和这个例子中除了class名字外,都是一样的呢?
ProviderSqlSource 初始化时不会调用 newInstance 方法。当 Mapper 处理所有的通用方法后,都已经不是 ProviderSqlSource 了,永远都没机会调用 newInstance 了。唯一会导致这个错误的原因就是配置错误导致通用方法没被处理。
你接口都集成的 MyMapper,你按文档配置 mappers 属性试试。
@abel533 看看错哪了呢?
又比对了一遍了。都有配置的:
mappers:
发现一个有意思地方: 我这边 通用mapper自动配置没有生效:
上面例子中spring 容器中有这些bean,我写的那个demo就没有
@abel533 感觉这是一个bug,看看是那个方面的原因导致的呢?
问题原因应该是:com.github.pagehelper.autoconfigure.MapperAutoConfiguration和 com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration 没有自动配置。
以MapperAutoConfiguration为例,Spring容器中是有SqlSessionFactory这个实例的,从下面的代码看,MapperAutoConfiguration 是应该会被自动配置,但实际情况是 ----- 没有实例化: @Configuration @ConditionalOnBean({SqlSessionFactory.class}) @EnableConfigurationProperties({MapperProperties.class}) @AutoConfigureAfter({MybatisAutoConfiguration.class}) public class MapperAutoConfiguration {
加个 @MapperScan
@abel533 感觉问题出在MapperAutoConfiguration.java的Condition条件上了 看看是不是应该把MapperAutoConfiguration.java上的注解 @ConditionalOnBean({SqlSessionFactory.class}) 改成 @ConditionalOnClass({SqlSessionFactory.class})
MapperScan已经加过了。 @MapperScan放在启动的那个class CookbookApplication.java上了
@abel533 这个bug不想跟了。回退到使用java config来配置PageInterceptor和通用Mapper. 现在已经Ok。
tips: 经过这个bug搞的,感觉现在离能写mybatis plugin只差一点点了 ☺^_^
@abel533
建议将MapperAutoConfiguration和PageHelperAutoConfiguration的实例化条件改为ConditionalOnClass
应该是spring boot中加载MapperAutoConfiguration和PageHelperAutoConfiguration的时机有差异
spring boot actuator中提供的信息显示,在加载通用Mapper和PageHelper的autoconfig时,SqlSessionFactory.class并没有实例化完成。
我这里的启动日志中:
MapperAutoConfiguration matched:
- @ConditionalOnBean (types: org.apache.ibatis.session.SqlSessionFactory; SearchStrategy: all) found bean 'sqlSessionFactory' (OnBeanCondition)
PageHelperAutoConfiguration matched:
- @ConditionalOnBean (types: org.apache.ibatis.session.SqlSessionFactory; SearchStrategy: all) found bean 'sqlSessionFactory' (OnBeanCondition)
你使用的 spring boot,以及 pagehelper 和 mapper 的 starter 版本是多少?
@abel533 都是从https://github.com/abel533/MyBatis-Spring-Boot.git copy过去的
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<!--mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
<!--pagehelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
@abel533 如果单独写一个项目,里面只有https://github.com/abel533/MyBatis-Spring-Boot.git 里面的业务逻辑,也是可以的。
但在https://github.com/helloworldtang/spring-boot-cookbook.git 这个学习用的小项目中,就会not Matched
@helloworldtang 遇到同样的问题,你解决了吗?
现在是能用了,具体什么原因也不清楚。 把相关配置都放在application,properties中就可以。
遇到这个问题了,
Caused by: org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.base.BaseSelectProvider.dynamicSQL).
Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.base.BaseSelectProvider
我的分析如下:
spring boot项目中用的是mybatis的:
@MapperScan(basePackages = { "com.xxx.mapper"})
而传统spring mvc项目中用的是tk.mybatis的:
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xxx.mapper" />
</bean>
spring-boot那种mapper扫描方式,少了一些 tk.mybatis.spring.mapper.MapperScannerConfigurer 中的操作。所以我猜想可能是这个原因导致。
看了很多spring-boot源码和文档,但是后面总结了一下,其实spring-boot并没有像官方说的那样简便易用,特别是涉及一些复杂配置,spring-boot管理起来很乱。所以,我接下来准备尝试把xml和spring mvc的注释方式结合起来使用,不知道效果会怎样。
@zollty 这个错误只有配置错的时候才会出现,就是没有处理通用接口方法导致的。
@abel533 据我深入分析,这不是配置错误,而是代码问题。@MapperScan
注解并不能代替tk.mybatis.spring.mapper.MapperScannerConfigurer,如果用@MapperScan
则少了对GenericBeanDefinition的改造、少了加入mapperHelper
。
为了验证这个说法,我将@MapperScan
换成了自己写的@MyMapperScan
,扫描注解时加上mapperHelper
并对BeanDefinitionRegistry registry
进行了处理,自然就解决了这个问题。
建议你提供一个tk.MapperScan,替换Mybatis自带那个。
@zollty 你用mapper-starter了吗?这个项目会自动处理通用接口。
大神们,有什么解决方案吗?我也遇到了类似的错误,所有的配置都对比了一遍,应该没什么错误,但是BaseSelectProvider初始化就是报错。
@fengcbo 你用的1.1.1版本的starter?
恩,用的是1.1.1版本的。只是在@Configuration中引用Mapper会报错,项目启动完成后就可以正常调用了
@fengcbo 这种情况会在初始化完成前调用,所以会出错。
哪有什么方法可以解决这个问题吗?