I have a single DynamoDB table which contains more than one type of Logical Entity. My table stores "Employees" and "Organizations" and creates a many-to-many relationship between the two of them.
I am struggling with how to use DynamoDBMapper to model both the entities and my table. Particularly when trying to write queries that will return both Employees and Organizations.
In my Java code, I've started by representing these entities using two classes.
Employee.java
@DynamoDBTable(tableName = "workplaces")
public class Employee() {
@DynamoDBHashKey(attributeName = "pk")
public String employeeId;
@DynamoDBRangeKey(attributeName = "sk")
public String sortKey
// Other attributes specific to employees, as well as getters and setters
}
And Organization.java:
@DynamoDBTable(tableName = "workplaces")
public class Organization() {
@DynamoDBHashKey(attributeName = "pk")
public String organizationId;
@DynamoDBRangeKey(attributeName = "sk")
public String sortKey
// Other attributes specific to organizations, as well as getters and setters
}
One of my query access patterns is, "Retrieve an organization's details and all of its employees". I have designed my table schema in a way which allows me to retrieve all of these items within a single query.
I'm struggling with how to write this query in Java using DynamoDbMapper. Both DynamoDBQueryExpression and the mapper.query() function require a class to instantiate and hydrate. Since my query result set will contain both types of objects, I don't think I can supply these functions with either Employee.class or Organization.class.
My idea was to just try supplying Object.class, but that doesn't work because DynamoDBMapper expects the supplied class to include the DynamoDB annotations.
Test.java:
DynamoDBMapper mapper = new DynamoDBMapper();
DynamoDBQueryExpression<Object> queryExpression = new DynamoDBQueryExpression<Object>()
.withHashKeyValues("blah")
.withRangeKeyCondition("blah");
List<Object> queryResult = mapper.query(Object.class, queryExpression);
I am thinking that the only way around this is to create a "master" class which truly represents all objects in my table, something like:
@DynamoDBTable(tableName = "workplaces")
public class WorkplaceItem() {
// All attributes from both the Employee and Organization classes
}
Then, all of my queries would be done on the WorkplaceItem class, and I'd be responsible for adding some business logic to convert a WorkplaceItem into a more specific Employee or Organization within the java code.
Is this the right approach? It would be a substantial change to my codebase so I'm curious if there is a better way to accomplish what I want before I start making this change.
Answering my own question here.
DynamoDBMapper cannot be used for my purpose, but I should still keep the individual classes and not create a single master class.
From this article by AWS: https://aws.amazon.com/blogs/database/amazon-dynamodb-single-table-design-using-dynamodbmapper-and-spring-boot/