Spring boot 当使用Spring数据JPA和Spring数据Cassandra时,请验证Spring Boot 1.3.1中的MappingException
我使用SpringBootStarter父级,让Spring管理我的项目的所有依赖项,并使用SpringDataCassandra和SpringDataJPA Spring boot starter父版本是1.2.8.RELEASE。最近我将该版本更新为1.3.1.RELEASE,并开始面临Spring数据Cassandra的一个奇怪问题Spring boot 当使用Spring数据JPA和Spring数据Cassandra时,请验证Spring Boot 1.3.1中的MappingException,spring-boot,spring-data-cassandra,Spring Boot,Spring Data Cassandra,我使用SpringBootStarter父级,让Spring管理我的项目的所有依赖项,并使用SpringDataCassandra和SpringDataJPA Spring boot starter父版本是1.2.8.RELEASE。最近我将该版本更新为1.3.1.RELEASE,并开始面临Spring数据Cassandra的一个奇怪问题 21:23:21.783 [localhost-startStop-1] WARN org.apache.catalina.loader.WebappCl
21:23:21.783 [localhost-startStop-1] WARN org.apache.catalina.loader.WebappClassLoaderBase - Failed to check for ThreadLocal references for web application [ROOT]
java.lang.UnsupportedOperationException: null
at com.zaxxer.hikari.util.FastList.iterator(FastList.java:209) ~[HikariCP-2.4.3.jar:na]
at org.apache.catalina.loader.WebappClassLoaderBase.loadedByThisOrChild(WebappClassLoaderBase.java:2195) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks(WebappClassLoaderBase.java:2105) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalsForLeaks(WebappClassLoaderBase.java:2060) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.loader.WebappClassLoaderBase.clearReferences(WebappClassLoaderBase.java:1575) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.loader.WebappClassLoaderBase.stop(WebappClassLoaderBase.java:1521) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.loader.WebappLoader.stopInternal(WebappLoader.java:447) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5517) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1424) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1413) [tomcat-embed-core-8.0.30.jar:8.0.30]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_72]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_72]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_72]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_72]
21:23:21.791 [main] ERROR org.springframework.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.service.intf.UserService com.sarvint.rest.UserController.uService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.repositories.UserRepository com.sarvint.service.UserServiceImpl.userRepo; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is org.springframework.data.cassandra.mapping.VerifierMappingExceptions: com.sarvint.domain.User:
Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:764) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:357) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1124) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1113) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at com.sarvint.Application.main(Application.java:18) [classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.service.intf.UserService com.sarvint.rest.UserController.uService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.repositories.UserRepository com.sarvint.service.UserServiceImpl.userRepo; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is org.springframework.data.cassandra.mapping.VerifierMappingExceptions: com.sarvint.domain.User:
Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
... 17 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.repositories.UserRepository com.sarvint.service.UserServiceImpl.userRepo; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is org.springframework.data.cassandra.mapping.VerifierMappingExceptions: com.sarvint.domain.User:
Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation
它说我必须用@Table等注释实体,但这些实体是Spring数据JPA
我用@Table等注释了Spring数据Cassandra的实体
开始上课:
@SpringBootApplication
@EnableJpaRepositories( repositoryFactoryBeanClass = GenericRepositoryFactoryBean.class )
@EntityScan("com.sarvint.domain")
@Import(CassandraConfig.class)
public class Application {
public static void main( String[] args ) throws Exception
{
SpringApplication.run(Application.class, args);
}
}
Spring数据JPA配置:
@Configuration
@ComponentScan( basePackages = "com.sarvint" )
@PropertySource( value = { "classpath:application.properties" } )
public class AppConfig extends WebMvcConfigurerAdapter {
@Autowired
private Environment environment;
@Override
public void configureDefaultServletHandling( DefaultServletHandlerConfigurer configurer )
{
configurer.enable();
}
@Bean
public DataSource dataSource()
{
HikariConfig config = new HikariConfig();
int poolSize = 20;
config.setMaximumPoolSize(poolSize);
config.setDataSourceClassName(environment.getRequiredProperty("spring.datasource.driver-class-name"));
config.addDataSourceProperty("url", environment.getRequiredProperty("spring.datasource.url"));
config.addDataSourceProperty("user", environment.getRequiredProperty("spring.datasource.username"));
config.addDataSourceProperty("password", environment.getRequiredProperty("spring.datasource.password"));
return new HikariDataSource(config);
}
Spring数据JPA实体:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table( name = "user" )
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "u_id" )
private Integer userId;
@Column( name = "u_first_name" )
private String firstName;
@Column( name = "u_last_name" )
private String lastName;
}
现在来看Spring数据Cassandra配置:
package com.sarvint.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
@Configuration
@PropertySource(value = { "classpath:cassandra.properties" })
@EnableCassandraRepositories(basePackages="com.sarvint.cassandra.domain")
public class CassandraConfig extends AbstractCassandraConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(CassandraConfig.class);
@Autowired
private Environment environment;
@Bean
public CassandraClusterFactoryBean cluster() {
LOG.info("INSIDE cluster()");
CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
cluster.setContactPoints(environment.getProperty("cassandra.contactpoints"));
cluster.setPort(Integer.parseInt(environment.getProperty("cassandra.port")));
return cluster;
}
@Override
protected String getKeyspaceName() {
LOG.info("INSIDE getting keyspace name");
return environment.getProperty("cassandra.keyspace");
}
@Bean
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
LOG.info("INSIDE cassandra mapping");
return new BasicCassandraMappingContext();
}
}
Spring Cassandra实体:
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
@Table( value = "biometric_param" )
public class BiometricParam {
@PrimaryKeyColumn(name="user_id",ordinal=0,type=PrimaryKeyType.PARTITIONED)
private Integer userId;
@PrimaryKeyColumn(name="workout_uuid",ordinal=1,type=PrimaryKeyType.PARTITIONED)
private String workoutUUID;
@PrimaryKeyColumn(name="bio_param_key",ordinal=2,type=PrimaryKeyType.CLUSTERED)
private String bioParamKey;
@Column(value="bio_param_val")
private Float bioParamValue;
}
卡桑德拉酒店
cassandra.contactpoints=127.0.0.1
cassandra.port=9042
cassandra.keyspace=test
谢谢你的帮助 尝试升级到HIKARIP2.4.4。它包含以下修复程序:
问题495:在自定义FastList上实现迭代器()方法以支持Tomcat
内存泄漏检测。
有什么问题?
这是Spring数据Cassandra中的一个bug。类路径上有多个Spring数据模块。在这种情况下,Spring数据试图找出特定存储库属于哪个模块。Spring Data Cassandra遗漏了标识您的JPA实体User
不属于Cassandra的位,因此Spring Data Cassandra尝试为您的UserRepository
创建一个存储库实例
如果启用DEBUG
日志记录,您将看到一些DEBUG
日志消息,表明Spring数据正在进入严格配置模式
为什么现在出现了这个bug,而不是早期的Spring启动版本?
SpringBoot1.3.0引入了SpringDataCassandra存储库的自动配置。由于此更改,Spring Boot执行的操作与您仅使用@EnableCassandraRepositories
配置的类似
只有使用多个Spring数据模块组合使用默认的EnableCassandraRepositories
才能发现此缺陷
那么,现在怎么办?
在application.properties
中设置spring.data.cassandra.repositories.enabled=false以禁用自动配置,因为您自己正在使用@EnableCassandraRepositories(basePackages=“com.sarvint.cassandra.domain”)
我创建了一个bug报告,所以如果您愿意,您可以跟踪进度。如果我在application.properties中添加spring.data.cassandra.repositories.enabled=false
,它说没有与spring数据JPAGreat相关的存储库类的构造函数,因此您摆脱了cassandra问题。接下来是JPA,所以创建一个包含另一个堆栈跟踪的新帖子。与此不同,我最初没有任何neo4j存储库。但它给了我和卡桑德拉一样的错误。然后我将spring.data.neo4j.repositories.enabled设置为false,它开始正常工作。感谢@mp911de提供此信息。看起来spring neo4j也存在同样的错误。这确实解决了FastList、HikariCp的问题,但没有解决实际的spring数据模块冲突!无论如何,谢谢你