我正在学习DynamoDB,所以我尝试使用Sping Boot 和DynamoDB做一个基本的项目。我检查了这些链接来成功运行这个应用程序,但失败了:(
- https://stackoverflow.com/a/57386532/2952011
- http://johnhunsley.blogspot.com/2016/11/spring-data-jpa-with-hash-range-key.html
- https://medium.com/@leohoc/dynamodb-and-spring-data-a81c546a1305
对于数据库设置,我使用了Docker。下面是我的组合文件:
version: '3.7'
services:
localstack:
container_name: localstack
image: localstack/localstack:latest
environment:
- DEBUG=1
- USE_SSL=0
- AWS_CBOR_DISABLE=1
- DOCKER_HOST=unix:///var/run/docker.sock
- HOSTNAME=localstack
- SERVICES=dynamodb
- AWS_DEFAULT_REGION=us-east-1
ports:
- '4566-4583:4566-4583'
volumes:
- ${TEMPDIR:-/tmp/localstack}:/var/lib/localstack
- /var/run/docker.sock:/var/run/docker.sock
- ./script/init-dynamodb.sh:/docker-entrypoint-initaws.d/init-dynamodb.sh
创建表的脚本如下所示:
#!/bin/bash
# -- > Create DynamoDb Table
echo Creating DynamoDb \'ItemInfo\' table ...
echo $(awslocal dynamodb create-table --cli-input-json '{
"TableName":"ItemInfo",
"KeySchema":
[
{"AttributeName":"id","KeyType":"HASH"}
],
"AttributeDefinitions":
[
{"AttributeName":"id","AttributeType":"S"}
],
"BillingMode":"PAY_PER_REQUEST"
}'
)
echo Creating DynamoDb \'Music\' table ...
echo $(awslocal dynamodb create-table --cli-input-json '{
"TableName":"Music",
"KeySchema":
[
{"AttributeName":"Artist","KeyType":"HASH"},
{"AttributeName":"SongTitle","KeyType":"RANGE"}
],
"AttributeDefinitions":
[
{"AttributeName":"Artist","AttributeType":"S"},
{"AttributeName":"SongTitle","AttributeType":"S"}
],
"ProvisionedThroughput":{
"WriteCapacityUnits": 5,
"ReadCapacityUnits": 5
},
"TableClass": "STANDARD"
}'
)
# --> List DynamoDb Tables
echo Listing tables ...
echo $(awslocal dynamodb list-tables)
因此,运行后:
sudo docker compose up -d
当我执行这个命令时:
aws --endpoint-url=http://localhost:4566 --region=us-east-1 dynamodb describe-table --table-name Music
我得到这个:
{
"Table": {
"AttributeDefinitions": [
{
"AttributeName": "Artist",
"AttributeType": "S"
},
{
"AttributeName": "SongTitle",
"AttributeType": "S"
}
],
"TableName": "Music",
"KeySchema": [
{
"AttributeName": "Artist",
"KeyType": "HASH"
},
{
"AttributeName": "SongTitle",
"KeyType": "RANGE"
}
],
"TableStatus": "ACTIVE",
"CreationDateTime": "2023-03-07T14:17:46.287000+06:00",
"ProvisionedThroughput": {
"LastIncreaseDateTime": "1970-01-01T06:00:00+06:00",
"LastDecreaseDateTime": "1970-01-01T06:00:00+06:00",
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 5,
"WriteCapacityUnits": 5
},
"TableSizeBytes": 0,
"ItemCount": 0,
"TableArn": "arn:aws:dynamodb:us-east-1:000000000000:table/Music",
"TableId": "bcce1ab3-8f0c-4b8f-9d55-6c69ec1ef2ad",
"Replicas": [],
"TableClassSummary": {
"TableClass": "STANDARD"
}
}
}
所以我相信创建表是可以的。现在我展示(DynamoDB Table)音乐类:
@DynamoDBTable(tableName = "Music")
public class Music implements Serializable {
@Id
private MusicId musicId;
public Music() {}
public Music(MusicId musicId) {
this.musicId = musicId;
}
public MusicId getMusicId() {
return musicId;
}
public void setMusicId(MusicId musicId) {
this.musicId = musicId;
}
@DynamoDBHashKey(attributeName = "Artist")
public String getArtist() {
return musicId != null ? musicId.getArtist() : null;
}
public void setArtist(String artist) {
if (musicId == null)
musicId = new MusicId();
musicId.setArtist(artist);
}
@DynamoDBRangeKey(attributeName = "SongTitle")
public String getSongTitle() {
return musicId != null ? musicId.getSongTitle() : null;
}
public void setSongTitle(String songTitle) {
if (musicId == null)
musicId = new MusicId();
musicId.setSongTitle(songTitle);
}
}
下面是MusicId(DynamoDB文档)类:
@DynamoDBDocument
public class MusicId implements Serializable {
private static final long serialVersionUID = 100L;
public MusicId() {
}
public MusicId(String artist, String songTitle) {
this.artist = artist;
this.songTitle = songTitle;
}
private String artist;
private String songTitle;
@DynamoDBHashKey(attributeName = "Artist")
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@DynamoDBRangeKey(attributeName = "SongTitle")
public String getSongTitle() {
return songTitle;
}
public void setSongTitle(String songTitle) {
this.songTitle = songTitle;
}
}
这里是音乐库:
@EnableScan
public interface MusicRepository extends CrudRepository<Music, MusicId> {
}
下面是实现DynamoDbService的DynamoDbServiceImpl:
@Service
public class DynamoDbServiceImpl implements DynamoDbService {
private final ItemInfoRepository itemInfoRepository;
private final MusicRepository musicRepository;
@Autowired
public DynamoDbServiceImpl(ItemInfoRepository itemInfoRepository, MusicRepository musicRepository) {
this.itemInfoRepository = itemInfoRepository;
this.musicRepository = musicRepository;
}
@Override
public void saveItem(ItemInfoDto dto) {
ItemInfo itemInfo = new ItemInfo();
itemInfo.setItemName(dto.getItemName());
itemInfo.setItemUrl(dto.getItemUrl());
itemInfoRepository.save(itemInfo);
}
@Override
public void saveMusic(MusicDto dto) {
Music music = new Music();
music.setArtist(dto.getArtist());
musicRepository.save(music);
}
}
下面是要配置的AwsDynamoDbConfig:
@Getter
@Setter
@Configuration
@EnableDynamoDBRepositories(basePackages = "com.mukit09.dynamodblearning.repository")
public class AwsDynamoDbConfig {
@Value("${config.aws.region}")
private String region;
@Value("${config.aws.dynamodb.url}")
private String dynamoDbEndpointUrl;
@Value("${config.aws.dynamodb.access-key}")
private String accessKey;
@Value("${config.aws.dynamodb.secret-key}")
private String secretKey;
@Bean(name = "amazonDynamoDB")
public AmazonDynamoDB amazonDynamoDB() {
return AmazonDynamoDBClientBuilder.standard()
.withCredentials(getCredentialsProvider())
.withEndpointConfiguration(getEndpointConfiguration(dynamoDbEndpointUrl))
.build();
}
private EndpointConfiguration getEndpointConfiguration(String url) {
return new EndpointConfiguration(url, region);
}
private AWSStaticCredentialsProvider getCredentialsProvider() {
return new AWSStaticCredentialsProvider(getBasicAWSCredentials());
}
private BasicAWSCredentials getBasicAWSCredentials() {
return new BasicAWSCredentials(accessKey, secretKey);
}
}
这些是www.example.com上的内容application.properties:
#dynamoDB
config.aws.region=us-east-1
config.aws.dynamodb.url=http://127.0.0.1:4566
config.aws.dynamodb.access-key=localstack
config.aws.dynamodb.secret-key=localstack
#log
logging.file.name=debug.log
logging.level.root= debug
这是我的gradle文件(build.gradle):
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.9'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'com.mukit09'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.github.derjust:spring-data-dynamodb:5.1.0'
implementation 'com.amazonaws:aws-java-sdk-dynamodb:1.12.420'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
}
tasks.named('test') {
useJUnitPlatform()
}
当我尝试运行此应用程序时,它无法保留此日志:
2023-03-07 17:32:17.375 ERROR 68881 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dynamoDbController' defined in file [/home/mukit09/code/java/dynamodb-learning/build/classes/java/main/com/mukit09/dynamodblearning/controller/DynamoDbController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dynamoDbServiceImpl' defined in file [/home/mukit09/code/java/dynamodb-learning/build/classes/java/main/com/mukit09/dynamodblearning/service/impl/DynamoDbServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'musicRepository' defined in com.mukit09.dynamodblearning.repository.MusicRepository defined in @EnableDynamoDBRepositories declared on AwsDynamoDbConfig: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/data/repository/core/support/ReflectionEntityInformation
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.25.jar:5.3.25]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.25.jar:5.3.25]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.9.jar:2.7.9]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.9.jar:2.7.9]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.9.jar:2.7.9]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.9.jar:2.7.9]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.9.jar:2.7.9]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.9.jar:2.7.9]
at com.mukit09.dynamodblearning.DynamodbLearningApplication.main(DynamodbLearningApplication.java:10) ~[main/:na]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dynamoDbServiceImpl' defined in file [/home/mukit09/code/java/dynamodb-learning/build/classes/java/main/com/mukit09/dynamodblearning/service/impl/DynamoDbServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'musicRepository' defined in com.mukit09.dynamodblearning.repository.MusicRepository defined in @EnableDynamoDBRepositories declared on AwsDynamoDbConfig: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/data/repository/core/support/ReflectionEntityInformation
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.25.jar:5.3.25]
... 19 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'musicRepository' defined in com.mukit09.dynamodblearning.repository.MusicRepository defined in @EnableDynamoDBRepositories declared on AwsDynamoDbConfig: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/data/repository/core/support/ReflectionEntityInformation
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.25.jar:5.3.25]
... 33 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/data/repository/core/support/ReflectionEntityInformation
at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016) ~[na:na]
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
at org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBEntityMetadataSupport.getEntityInformation(DynamoDBEntityMetadataSupport.java:125) ~[spring-data-dynamodb-5.1.0.jar:5.1.0]
at org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactory.getEntityInformation(DynamoDBRepositoryFactory.java:104) ~[spring-data-dynamodb-5.1.0.jar:5.1.0]
at org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactory.getDynamoDBRepository(DynamoDBRepositoryFactory.java:128) ~[spring-data-dynamodb-5.1.0.jar:5.1.0]
at org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactory.getTargetRepository(DynamoDBRepositoryFactory.java:150) ~[spring-data-dynamodb-5.1.0.jar:5.1.0]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:325) ~[spring-data-commons-2.7.8.jar:2.7.8]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:323) ~[spring-data-commons-2.7.8.jar:2.7.8]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:231) ~[spring-data-commons-2.7.8.jar:2.7.8]
at org.springframework.data.util.Lazy.get(Lazy.java:115) ~[spring-data-commons-2.7.8.jar:2.7.8]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:329) ~[spring-data-commons-2.7.8.jar:2.7.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.25.jar:5.3.25]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.25.jar:5.3.25]
... 44 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.data.repository.core.support.ReflectionEntityInformation
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
... 64 common frames omitted
Process finished with exit code 1
作为一个学习者,我肯定犯了一些错误。你能帮我找出我犯的错误吗?
1条答案
按热度按时间wydwbb8l1#
这是一个已知的问题,因为您可以找到here和here,因为Spring〉2.2不受支持。
有一个分叉,它可能工作,但我没有测试:
https://github.com/boostchicken/spring-data-dynamodb.