Open helloworldtang opened 7 years ago
重新切了个分支: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 这种情况会在初始化完成前调用,所以会出错。
哪有什么方法可以解决这个问题吗?
参考:Spring Boot - 配置排序依赖技巧
让你的配置类在 MapperAutoConfiguration
配置类后面执行。
按照您文章中说的配置了org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration,\ com.xxxx.ShiroConfiguration
ShiroConfiguration 没有让spring boot扫描到,但是错误依旧存在。 在网上搜索了好多关于这个错误的问答,感觉都是没有什么结果,希望您能在常见问题中提供一下解决方案,或者能够提供一个相关的项目示例。
在 MapperAutoConfiguration
和 你的配置类中断点看看那个先执行。
上面的配置写错了,第一个应该是com.github.pagehelper.autoconfigure.MapperAutoConfiguration。 不过debug看了后,在META-INF/spring.factories 中加入上面的配置后依然是我的ShiroConfiguration先执行。
ShiroConfiguration 注解怎么配置的?
只有一个Configuration注解
今天大概读了一下spring boot 关于spring.factories解析的过程,spring boot在解析完org.springframework.boot.autoconfigure.EnableAutoConfiguration后的配置后会对结果进行再一次的排序,所以这个配置的顺序不能保证spring boot的解析顺序。您提供的那个方法好像并不可行。
同样的问题,@Configuration类内面用到Mapper,结果出现这个错误了。。。
Configuration的加载是在Auto Configuration之前的,有几种方式可以让Auto Configuration以前加载,作者的实现没有考虑到Configuration中使用Mapper的情况,要解决目前只能自己重写starter(没找到其他方式)。
这里确实有问题。加载太早以至于没有初始化。
我也遇到这个问题了,只能Java代码配置,没法用starter
仿照作者的starter重写了一个,解决了这个问题 https://github.com/fengcbo/mapper-spring-boot
应该不需要你重写一个starter吧,可以在你使用mapper的configuration上加上
@AutoConfigureAfter(MapperAutoConfiguration.class)
的注解手动控制顺序就好了啊
AutoConfigureAfter不能控制Configuration和Auo-Configuration的加载顺序,我测试的是加上AutoConfigureAfter依然不能解决问题,你的应该是没在Configuration使用通用Mapper吧
@ZuiSong @fengcbo 看这里:http://blog.csdn.net/isea533/article/details/53975720
最终解决方案是什么呢?
@cgnq 使用提供的mapper-starter就行。
嗯,还有一个问题,假如A用到B,不管怎么配置,B一定会先加载。我用shiro的ShiroFilterFactoryBean在配置的时候用通用mapper加入数据库数据,用了spring.factories也没用,最终的解决方案是让ShiroFilterFactoryBean先加载,在写一个
异常信息:
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.base.BaseInsertProvider.dynamicSQL). Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.base.BaseInsertProvider
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
.........................................此处省略很多无用信息.......................................
Caused by: org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.base.BaseInsertProvider.dynamicSQL). Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.base.BaseInsertProvider
at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:135)
.........................................此处省略很多无用信息.......................................
Caused by: java.lang.InstantiationException: tk.mybatis.mapper.provider.base.BaseInsertProvider
at java.lang.Class.newInstance(Class.java:427)
at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:117)
... 147 common frames omitted
Caused by: java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseInsertProvider.
解决方案: 使用MapperScan注解时使用 tk.mybatis.spring.annotation.MapperScan 替换 org.mybatis.spring.annotation.MapperScan,搞定问题,不知道与上面的仁兄是不是同样的问题,这算不算一种解决方案呢?另外如果这里能避免注解的再定义,只使用org.mybatis.spring.annotation.MapperScan 注解就完美了^o^!
@760374564 你可以看看文档中配置 Configuration 的用法,用这种方式都不需要 starter,只依赖 mapper 就行了。
错误: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.()
at java.lang.Class.getConstructor0(Class.java:3082)
相关代码已上传到github:https://github.com/helloworldtang/SpringBootCookbook rest接口:/tx/post 所在class: com.tangcheng.rest.TxController