Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Issue #76 - Same field as DynamoDBRangeKey and DynamoIndexDBRangeKey is causing issue #131

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package org.socialsignin.spring.data.dynamodb.domain.sample;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProjectionType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static org.junit.Assert.assertEquals;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {DynamoDBLocalResource.class, DuplicateColumnUsageTest.DuplicateColumnUsageTestConfig.class})
public class DuplicateColumnUsageTest {


@Configuration
@EnableDynamoDBRepositories(basePackages = "org.socialsignin.spring.data.dynamodb.domain.sample")
static class DuplicateColumnUsageTestConfig {

}


@Before
public void setUp() {
// DynamoDBLocalResource.createTable(ddb, Playlist.class);
List<AttributeDefinition> ad = new ArrayList<>();
ad.add(new AttributeDefinition("Genre", ScalarAttributeType.S));
ad.add(new AttributeDefinition("PlaylistName", ScalarAttributeType.S));
ad.add(new AttributeDefinition("UserName", ScalarAttributeType.S));

List<KeySchemaElement> ks = new ArrayList<>();
ks.add(new KeySchemaElement("UserName", KeyType.HASH));
ks.add(new KeySchemaElement("PlaylistName", KeyType.RANGE));

List<KeySchemaElement> gsiks = new ArrayList<>();
gsiks.add(new KeySchemaElement("Genre", KeyType.HASH));
gsiks.add(new KeySchemaElement("PlaylistName", KeyType.RANGE));

List<GlobalSecondaryIndex> gsis = new ArrayList<>();
gsis.add(new GlobalSecondaryIndex()
.withIndexName("Genre-PlaylistName-index")
.withKeySchema(gsiks)
.withProjection(new Projection().withProjectionType(ProjectionType.ALL))
.withProvisionedThroughput(new ProvisionedThroughput(10L, 10L)));

CreateTableRequest ctr = new CreateTableRequest();
ctr.withTableName("playlist");
ctr.withAttributeDefinitions(ad);
ctr.withKeySchema(ks);
ctr.withGlobalSecondaryIndexes(gsis);
ctr.withProvisionedThroughput(new ProvisionedThroughput(10L, 10L));

ddb.createTable(ctr);
}


@Autowired
private PlaylistRepository playlistRepository;
@Autowired
private AmazonDynamoDB ddb;


private Playlist generatePlaylist(String genre, String playlistName) {
final String userName = "userName-" + UUID.randomUUID().toString();
final String displayName = "displayName-" + UUID.randomUUID().toString();
PlaylistId id = new PlaylistId(userName, playlistName);

Playlist playlist = new Playlist(id);
playlist.setDisplayName(displayName);
playlist.setGenre(genre);

return playlist;
}

@Test
public void testGsiSharedRange() {
final String GENRE = "GENRE";
playlistRepository.save(generatePlaylist(GENRE, "1"));
playlistRepository.save(generatePlaylist(GENRE, "2"));
playlistRepository.save(generatePlaylist(GENRE, "3"));
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}

assertEquals(3, playlistRepository.findByGenre(GENRE).size());

assertEquals(1, playlistRepository.findByGenreAndPlaylistName(GENRE, "2").size());

List<Playlist> actual = playlistRepository.findByGenreAndPlaylistNameBetween(GENRE, "2", "3");

assertEquals(2, actual.size());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

Expand All @@ -37,20 +38,28 @@
public class HashRangeKeyIT {

@Autowired
PlaylistRepository playlistRepository;
private PlaylistRepository playlistRepository;

@Test
public void runCrudOperations() {
final String displayName = "displayName" + UUID.randomUUID().toString();
private Playlist generatePlaylist(String genre, String displayName) {
final String userName = "userName-" + UUID.randomUUID().toString();
final String playlistName = "playlistName-" + UUID.randomUUID().toString();
PlaylistId id = new PlaylistId(userName, playlistName);

Optional<Playlist> actual = playlistRepository.findById(id);
assertFalse(actual.isPresent());

Playlist playlist = new Playlist(id);
playlist.setDisplayName(displayName);
playlist.setGenre(genre);

return playlist;
}

@Test
public void runCrudOperations() {
String displayName = "displayName" + UUID.randomUUID().toString();
Playlist playlist = generatePlaylist("genre-" + UUID.randomUUID().toString(), displayName);
PlaylistId id = playlist.getId();

Optional<Playlist> actual = playlistRepository.findById(id);
assertFalse(actual.isPresent());

playlistRepository.save(playlist);

Expand All @@ -60,4 +69,16 @@ public void runCrudOperations() {
assertEquals(id.getPlaylistName(), actual.get().getPlaylistName());
assertEquals(id.getUserName(), actual.get().getUserName());
}

@Test
public void testGsiSharedRange() {
final String GENRE = "GENRE";
playlistRepository.save(generatePlaylist(GENRE, "1"));
playlistRepository.save(generatePlaylist(GENRE, "2"));
playlistRepository.save(generatePlaylist(GENRE, "3"));

List<Playlist> actual = playlistRepository.findByGenreAndPlaylistNameBetween(GENRE, "2", "3");

assertEquals(2, actual.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIgnore;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import org.springframework.data.annotation.Id;
Expand All @@ -27,13 +30,19 @@ public class Playlist {
@Id
private PlaylistId playlistId;
private String displayName;
private String genre;

public Playlist() {
}

public Playlist(PlaylistId playlistId) {
this.playlistId = playlistId;
}

@DynamoDBIgnore
public PlaylistId getId() {
return this.playlistId;
}

@DynamoDBAttribute(attributeName="DisplayName")
public String getDisplayName() {
Expand All @@ -57,6 +66,7 @@ public void setUserName(String userName) {
}

@DynamoDBRangeKey(attributeName = "PlaylistName")
@DynamoDBIndexRangeKey(attributeName = "PlaylistName", globalSecondaryIndexName="Genre-PlaylistName-index")
public String getPlaylistName() {
return playlistId != null ? playlistId.getPlaylistName() : null;
}
Expand All @@ -67,4 +77,13 @@ public void setPlaylistName(String playlistName) {
}
playlistId.setPlaylistName(playlistName);
}

@DynamoDBIndexHashKey(attributeName = "Genre", globalSecondaryIndexName="Genre-PlaylistName-index")
public String getGenre() {
return this.genre;
}

public void setGenre(String genre) {
this.genre = genre;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@
*/
package org.socialsignin.spring.data.dynamodb.domain.sample;

import java.util.List;

import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
import org.springframework.data.repository.CrudRepository;

@EnableScan
public interface PlaylistRepository extends CrudRepository<Playlist, PlaylistId> {
List<Playlist> findByGenre(String genre);
List<Playlist> findByGenreAndPlaylistName(String genre, String playlistName);
List<Playlist> findByGenreAndPlaylistNameBetween(String genre, String startPlaylistName, String endPlaylistName);

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public static <T> CreateTableResult createTable(AmazonDynamoDB ddb, Class<T> dom

Optional<String> rangeKey = Optional.empty();
if (entityInfo instanceof DynamoDBIdIsHashAndRangeKeyEntityInformation) {
rangeKey = Optional.of(((DynamoDBIdIsHashAndRangeKeyEntityInformation)entityInfo).getRangeKeyPropertyName());
rangeKey = Optional.of(((DynamoDBIdIsHashAndRangeKeyEntityInformation)entityInfo).getRangeKeyPropertyName())
.flatMap(e -> entityInfo.getOverriddenAttributeName(e));
}

return createTable(ddb, tableName, hashKey, rangeKey);
Expand Down
26 changes: 26 additions & 0 deletions src/test/resources/playlist_table.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,34 @@
{
"AttributeName": "PlaylistName",
"AttributeType": "S"
},
{
"AttributeName": "Genre",
"AttributeType": "S"
}
],
"GlobalSecondaryIndexes": [
{
"IndexName": "Genre-PlaylistName-index",
"KeySchema": [
{
"AttributeName": "Genre",
"KeyType": "HASH"
},
{
"AttributeName": "PlaylistName",
"KeyType": "RANGE"
}
],
"Projection": {
"ProjectionType": "ALL"
},
"ProvisionedThroughput": {
"ReadCapacityUnits": "10",
"WriteCapacityUnits": "10"
}
}
],
"KeySchema": [
{
"AttributeName": "UserName",
Expand Down