MyBatis-Spring-Boot icon indicating copy to clipboard operation
MyBatis-Spring-Boot copied to clipboard

该项目代码添加 spring boot devtools 时,出现java.lang.ClassCastException问题

Open GuidoPaul opened this issue 9 years ago • 10 comments

问题重现

pom.xml 中添加 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>

运行 spring-boot:run 点击 修改 操作,如访问http://localhost:8181/countries/view/1,出现java.lang.ClassCastException: tk.mybatis.springboot.model.Country cannot be cast to tk.mybatis.springboot.model.Country

GuidoPaul avatar Jun 18 '16 07:06 GuidoPaul

Hi,这个问题有解决方案? 尝试加了:restart.include.mybatiscommon=/mapper-[\w-]+.jar到spring-devtools.properties 还是无效。

问题确认: selectByPrimaryKey(xx)返回的对象是来源于AppClassLoader,其它因为配置了devtools使用了RestartClassLoader。 使用mybatis自定义查询方法返回的对象也是来源于RestartClassLoader.

tsball avatar Sep 10 '16 06:09 tsball

@tsball 你这应该是正则表达式的问题,需要匹配的是 mapper-3.3.9(当前引入的版本号).jar 试试 restart.include.mybatiscommon=/mapper-\\d+(\\.\\d+){0,2}.jar

reference:using-boot-devtools-customizing-classload

noob9527 avatar Dec 14 '16 15:12 noob9527

http://stackoverflow.com/questions/826319/classcastexception-when-casting-to-the-same-class 我也遇到了这种问题,查找了半天,还是不能解决

workcheng avatar Feb 15 '17 09:02 workcheng

@noob9527 我用了你的那个配置还是不行,直接启动就报错,这是我的pom.xml: `<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>demo</name>
<description>Demo project for Spring Boot</description>

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.5.1.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	<java.version>1.8</java.version>
    <!--数据库-->
    <ojdbc.version>12.1.0.1</ojdbc.version>
</properties>

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
	<!--添加对web的支持-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<!--zuul-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-zuul</artifactId>
		<version>1.2.5.RELEASE</version>
	</dependency>
	<!--Spring Boot Actuator-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>
	<!--开发环境的调试修改实时生效-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
		<optional>true</optional>
	</dependency>
    <!--mybatis-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.2.0</version>
    </dependency>
    <!--mapper-->
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>1.0.0</version>
    </dependency>
    <!--druid-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.0.11</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <!--test-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!--oracle-->
    <dependency>
        <groupId>oracle</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>${ojdbc.version}</version>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
</dependencies>

<build>
	<plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
	</plugins>
</build>
` 这是启动报错信息: `Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. 2017-02-15 17:11:48.602 ERROR 6332 --- [ restartedMain] o.s.boot.SpringApplication : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.github.pagehelper.autoconfigure.MapperAutoConfiguration': Invocation of init method failed; nested exception is java.lang.RuntimeException: tk.mybatis.mapper.provider.EmptyProvider中缺少selectOne方法! at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) at com.example.Application.main(Application.java:25) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) Caused by: java.lang.RuntimeException: tk.mybatis.mapper.provider.EmptyProvider中缺少selectOne方法! at tk.mybatis.mapper.mapperhelper.MapperHelper.fromMapperClass(MapperHelper.java:159) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:173) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:179) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:179) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:179) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:179) at com.github.pagehelper.autoconfigure.MapperAutoConfiguration.addPageInterceptor(MapperAutoConfiguration.java:64) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) ... 23 common frames omitted `

workcheng avatar Feb 15 '17 09:02 workcheng

@workcheng 去掉 devtool 就行,上面的配置不行,你要排除的类是你自己实体所在的 jar 包,这么配置也不方便。

abel533 avatar Feb 15 '17 12:02 abel533

这个问题解决方式只能在pom.xml中去掉 devtool吗?是否还有其他方式?

yanghdx avatar Feb 22 '17 08:02 yanghdx

@yanghdx spring boot dev-tool 对第三方jar包使用"base" class loader 对IDE project目录下的Class使用"restart" class loader restart.include.mybatiscommon=/mapper-\\d+(\\.\\d+){0,2}.jar这行配置是告诉devtool使用"restart" class loader 来加载mapper jar包中的类,一般来说这样就可以解决问题了。

noob9527 avatar Feb 22 '17 09:02 noob9527

@noob9527 添加配置后,pagehelper 报错。信息是: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.github.pagehelper.autoconfigure.MapperAutoConfiguration': Invocation of init method failed; nested exception is java.lang.RuntimeException: tk.mybatis.mapper.provider.EmptyProvider中缺少selectOne方法!

yanghdx avatar Feb 22 '17 10:02 yanghdx

@yanghdx 这是通用 Mapper 报错。。

abel533 avatar Feb 22 '17 13:02 abel533

我这么配置是好使的(正则就是匹配mybatis、mapper、pagehelper开头的全部,比较暴力一些) restart.include.pagehelpercommon=/pagehelper..jar restart.include.mybatiscommon=/mybatis..jar restart.include.mappercommon=/mapper.*.jar

yanghdx avatar Mar 04 '17 03:03 yanghdx