Spring 数据 Redis InvocationTargetException
Spring Data Redis InvocationTargetException
我目前正在尝试 Spring Data Redis,以便获取数据并将其放入 Redis 存储库。但是,在 运行 使用 mvn spring-boot:run
连接我的应用程序后,它总是 returns 错误并显示以下消息:
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.7.RELEASE:run (default-cli) on project networkprofile-bs-redis-poc: An exception occurred while running. null: InvocationTargetException: Invalid bean definition with name 'metadataRepository' defined in null: Cannot register bean definition [Root bean: class [org.springframework.data.redis.repository.support.RedisRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] for bean 'metadataRepository': There is already [Root bean: class [org.springframework.data.jdbc.repository.support.JdbcRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound. -> [Help 1]
我的代码中有两个存储库接口,MetadataRepository
和 ProfileRepository
,由于某种原因,错误在这两个接口之间来回切换,相同的 InvocationTargetException
。
元数据存储库
package xxx.repository;
import org.springframework.data.repository.CrudRepository;
import xxx.model.redis.Metadata;
public interface MetadataRepository extends CrudRepository<Metadata, String> {}
ProfileRepository
package xxx.repository;
import org.springframework.data.repository.CrudRepository;
import xxx.model.redis.Profile;
public interface ProfileRepository extends CrudRepository<Profile, String> {
Profile findByMsisdnAndProfile(String msisdn, String profile);
}
pom.xml
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
</parent>
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
...
<axiom.version>1.2.21</axiom.version>
<springfox.version>2.9.2</springfox.version>
...
</properties>
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-api</artifactId>
<version>${axiom.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-impl</artifactId>
<version>${axiom.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
我设置了一些 Redis 配置如下:
package xxx.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
@Configuration
@EnableRedisRepositories
public class RedisConfig {
@Value("${xxx.redis.host}")
private String redisHost;
@Value("${xxx.redis.port}")
private int redisPort;
@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(){
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(lettuceConnectionFactory());
template.afterPropertiesSet();
return template;
}
}
我不太确定是什么原因导致的,因为这与引发 BeanDefinitionOverrideException
.
的类似问题不同
我的目标是让我的应用程序 运行 没有问题,因此我需要查明造成这种情况的原因。也许我做错了什么?
更新
我发现 spring-boot-starter-data-jdbc
和 spring-boot-starter-data-redis
在我的构建中引起了冲突,导致 InvocationTargetException
。排除 JDBC 依赖项后,InvocationTargetException
消失。
但是,这样做会破坏我的其他需要 JDBC 连接的模块。因此,在我的案例中,我需要 JDBC 和 Redis 依赖项。
我被类似的问题困了将近两天,但终于弄明白了。问题是,当项目中使用多个 Spring 数据模块时, Spring 框架进入严格的存储库配置模式,并在底层使用不同的检测机制,以识别哪个存储库属于哪个持久化技术(解释here).
在您的例子中,使用了两个 Spring 数据模块,即 spring-data-jdbc 和 spring-data-redis。因此,在您的项目中定义的 ProfileRepository 和 MetadataRepository 可以用作 spring-data-jdbc 和 spring-data-redis 的存储库。解决这个问题的一种方法是使用module specific annotations。例如,要将 ProfileRepository 定义为与 Redis 相关的 Repository,您必须将 Profile class 定义为 :
@RedisHash("Profile")
public class Profile implements Serializable {
// fields and getters/setters as usual
}
或者,如果您想将 ProfileRepository 定义为与 JDBC 相关的存储库,则必须将您的个人资料 class 定义为:
@Table("Profile")
public class Profile implements Serializable {
// fields and getters/setters as usual
}
我目前正在尝试 Spring Data Redis,以便获取数据并将其放入 Redis 存储库。但是,在 运行 使用 mvn spring-boot:run
连接我的应用程序后,它总是 returns 错误并显示以下消息:
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.7.RELEASE:run (default-cli) on project networkprofile-bs-redis-poc: An exception occurred while running. null: InvocationTargetException: Invalid bean definition with name 'metadataRepository' defined in null: Cannot register bean definition [Root bean: class [org.springframework.data.redis.repository.support.RedisRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] for bean 'metadataRepository': There is already [Root bean: class [org.springframework.data.jdbc.repository.support.JdbcRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound. -> [Help 1]
我的代码中有两个存储库接口,MetadataRepository
和 ProfileRepository
,由于某种原因,错误在这两个接口之间来回切换,相同的 InvocationTargetException
。
元数据存储库
package xxx.repository;
import org.springframework.data.repository.CrudRepository;
import xxx.model.redis.Metadata;
public interface MetadataRepository extends CrudRepository<Metadata, String> {}
ProfileRepository
package xxx.repository;
import org.springframework.data.repository.CrudRepository;
import xxx.model.redis.Profile;
public interface ProfileRepository extends CrudRepository<Profile, String> {
Profile findByMsisdnAndProfile(String msisdn, String profile);
}
pom.xml
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
</parent>
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
...
<axiom.version>1.2.21</axiom.version>
<springfox.version>2.9.2</springfox.version>
...
</properties>
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-api</artifactId>
<version>${axiom.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-impl</artifactId>
<version>${axiom.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
我设置了一些 Redis 配置如下:
package xxx.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
@Configuration
@EnableRedisRepositories
public class RedisConfig {
@Value("${xxx.redis.host}")
private String redisHost;
@Value("${xxx.redis.port}")
private int redisPort;
@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(){
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(lettuceConnectionFactory());
template.afterPropertiesSet();
return template;
}
}
我不太确定是什么原因导致的,因为这与引发 BeanDefinitionOverrideException
.
我的目标是让我的应用程序 运行 没有问题,因此我需要查明造成这种情况的原因。也许我做错了什么?
更新
我发现 spring-boot-starter-data-jdbc
和 spring-boot-starter-data-redis
在我的构建中引起了冲突,导致 InvocationTargetException
。排除 JDBC 依赖项后,InvocationTargetException
消失。
但是,这样做会破坏我的其他需要 JDBC 连接的模块。因此,在我的案例中,我需要 JDBC 和 Redis 依赖项。
我被类似的问题困了将近两天,但终于弄明白了。问题是,当项目中使用多个 Spring 数据模块时, Spring 框架进入严格的存储库配置模式,并在底层使用不同的检测机制,以识别哪个存储库属于哪个持久化技术(解释here).
在您的例子中,使用了两个 Spring 数据模块,即 spring-data-jdbc 和 spring-data-redis。因此,在您的项目中定义的 ProfileRepository 和 MetadataRepository 可以用作 spring-data-jdbc 和 spring-data-redis 的存储库。解决这个问题的一种方法是使用module specific annotations。例如,要将 ProfileRepository 定义为与 Redis 相关的 Repository,您必须将 Profile class 定义为 :
@RedisHash("Profile")
public class Profile implements Serializable {
// fields and getters/setters as usual
}
或者,如果您想将 ProfileRepository 定义为与 JDBC 相关的存储库,则必须将您的个人资料 class 定义为:
@Table("Profile")
public class Profile implements Serializable {
// fields and getters/setters as usual
}