Hi Darshan,
Thanks for reaching out. You didn’t provide a lot of details about what sort of errors you’re seeing, so I created an example which I hope may be illustrative.
I have created a Car
class which contains a BasicInformation
instance and a PartInformation
instance. The BasicInformation
is simply a class with fields and no other objects. The PartInformation
however has 2 lists of items, PartDetail
and CustomPart
. I was thinking that PartDetail
might be standard parts and hence be referenced to parts in another set, but the CustomPart
would be something specific to that Car
so would probably be embedded.
This allows you to see different sort of approaches. I’ve put all my Embed
objects as MAP
s to make reading easier, but you can obviously change this to lists as necessary.
There are 2 ways of doing external configuration, using code or YAML files. The YAML file can be specified either as an external file or as a String
. I’ve taken the latter approach to keep everything in the same file.
This sample code shows both YAML and code approaches. Both produce the same result, but the code one did expose an issue which I’ve fixed in code and will check in shortly. So if you need to use this now, I would recommend the YAML approach.
Please let me know if you have any further questions. Note that I’m using Lombok to minimize the amount of code, this is definitely not a requirement.
Output in AQL looks like:
aql> select * from test.car
*************************** 1. row ***************************
id: "1010-2324-23231"
information: MAP('{"make":"Toyota", "model":"Corolla", "year":1985}')
partInfo: MAP('{"customParts":{101:{"description":"Lime green custom spoiler with wings", "id":101, "name":"spoiler"}, 102:{"description":"See any Bond movie", "id":102, "name":"rocket lancher"}, 103:{"description":"Great way to deal with those annoying passengers", "id":103, "name":"ejector seats"}}, "parts":[1, 2, 3]}')
1 row in set (0.019 secs)
Note that I’m using RAW mode here as JSON output will hide the non-String keys of the CustomPart
s, making it look like they’re not saved in the database when they clearly are.
package com.timf;
import java.util.Arrays;
import java.util.List;
import com.aerospike.client.AerospikeClient;
import com.aerospike.client.IAerospikeClient;
import com.aerospike.mapper.annotations.AerospikeEmbed.EmbedType;
import com.aerospike.mapper.annotations.AerospikeReference.ReferenceType;
import com.aerospike.mapper.tools.AeroMapper;
import com.aerospike.mapper.tools.configuration.ClassConfig;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
public class DiscussQuestion20240605 {
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class BasicInformation {
private String make;
private String model;
private int year;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class PartDetail {
private long id;
private String name;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class CustomPart {
long id;
private String name;
private String description;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class PartInformation {
private List<PartDetail> parts;
private List<CustomPart> customParts;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Car {
private String id;
private BasicInformation information;
private PartInformation partInfo;
}
public static void main(String[] args) throws Exception {
IAerospikeClient client = new AerospikeClient("localhost", 3100);
// The configuration files are for code-based config
ClassConfig carConfig = new ClassConfig.Builder(Car.class)
.withKeyField("id")
.withNamespace("test")
.withSet("car")
.withFieldNamed("information").beingEmbeddedAs(EmbedType.MAP)
.withFieldNamed("partInfo").beingEmbeddedAs(EmbedType.MAP)
.build();
ClassConfig basicInfoConfig = new ClassConfig.Builder(BasicInformation.class)
.build();
ClassConfig partInfoConfig = new ClassConfig.Builder(PartInformation.class)
.withFieldNamed("customParts").beingEmbeddedAs(EmbedType.MAP, EmbedType.MAP)
// .withFieldNamed("parts").
.withFieldNamed("parts").beingReferencedBy(ReferenceType.ID)
.build();
ClassConfig partDetailConfig = new ClassConfig.Builder(PartDetail.class)
.withKeyField("id")
.withNamespace("test")
.withSet("partDetail")
.build();
ClassConfig customPartConfig = new ClassConfig.Builder(CustomPart.class)
.withKeyField("id")
.build();
// This is for YAML based config
String configYaml = """
classes:
- class: com.timf.DiscussQuestion20240605$Car
namespace: test
set: car
key:
field: id
bins:
- field: information
embed:
type: MAP
- field: partInfo
embed:
type: MAP
- class: com.timf.DiscussQuestion20240605$BasicInformation
- class: com.timf.DiscussQuestion20240605$PartDetail
key:
field: id
namespace: test
set: partDetail
- class: com.timf.DiscussQuestion20240605$CustomPart
key:
field: id
- class: com.timf.DiscussQuestion20240605$PartInformation
bins:
- field: customParts
embed:
type: MAP
elementType: MAP
- field: parts
reference:
type: ID
lazy: false
batchLoad: true
""";
// Uncomment this for code-based config
// AeroMapper mapper = new AeroMapper.Builder(client)
// .withClassConfigurations(carConfig,
// basicInfoConfig,
// partInfoConfig,
// partDetailConfig,
// customPartConfig
// )
// .build();
// Uncomment this for YAML based config
AeroMapper mapper = new AeroMapper.Builder(client)
.withConfiguration(configYaml)
.build();
PartDetail part1 = new PartDetail(1, "wheels");
PartDetail part2 = new PartDetail(2, "dashboard");
PartDetail part3 = new PartDetail(3, "radiator");
CustomPart custPart1 = new CustomPart(101, "spoiler", "Lime green custom spoiler with wings");
CustomPart custPart2 = new CustomPart(102, "rocket lancher", "See any Bond movie");
CustomPart custPart3 = new CustomPart(103, "ejector seats", "Great way to deal with those annoying passengers");
PartInformation partInformation = new PartInformation(
Arrays.asList(part1, part2, part3),
Arrays.asList(custPart1, custPart2, custPart3)
);
BasicInformation basicInfo = new BasicInformation("Toyota", "Corolla", 1985);
Car car = new Car("1010-2324-23231", basicInfo, partInformation);
mapper.save(part1, part2, part3);
mapper.save(car);
Car readCar = mapper.read(Car.class, car.getId());
System.out.println("Read: " + readCar);
}
}