Spring boot 当使用Spring数据JPA和Spring数据Cassandra时,请验证Spring Boot 1.3.1中的MappingException

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

我使用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.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数据模块冲突!无论如何,谢谢你