I have a JPA Entity where I need to reference a list of nested object references.
I do not want a separate Entity and separate table for this nested object to not pollute my DB schema.
@ElementCollection
only work with serializable types so this is one is out.
@Embeddable
wouldn't work with List
.
The object that I would like to store is as follows:
Object {
private UUID id;
private TypeEnum type;
private SecondTypeEnum secondType;
}
What options do I have?
Tried with @ElementCollection
, separate Entity and @Embeddable
The idea is to convert a list of objects to string. SpringBoot uses jackson
library for manipulating json https://github.com/FasterXML/jackson. There is ObjectMapper
class in this library that can convert Java objects to String and vice versa. Note that list of objects is also an Object in Java.
@Service
public class MyService {
@Autowired
MyRepository myRepository;
@Autowired
ObjectMapper objectMapper;
public MyEntity saveObjects(List<MyObject> objects) throws JsonProcessingException {
String json = objectMapper.writeValueAsString(objects); // convert list of objects to string
MyEntity myEntity = new MyEntity(); // create new entity
myEntity.id = UUID.randomUUID(); // set id
myEntity.objects = json; // set objects
return myRepository.save(myEntity); // save entity in database
}
public List<MyObject> readObjects(UUID id) throws JsonProcessingException {
System.out.println("reading id " + id);
MyEntity myEntity = myRepository.findById(id).orElseThrow(); // read entity from database
String json = myEntity.objects; // get field objects as string
System.out.println(json); // print json as string
return objectMapper.readValue(json,
new TypeReference<List<MyObject>>() {}
); // convert json string to list of objects
}
}
public class MyObject {
public UUID id;
// other fields here - type, second type etc
}
@Entity
@Table(name = "example")
public class MyEntity {
@Id
public UUID id;
public String objects; // list of MyObjects as json
}
public interface MyRepository extends JpaRepository<MyEntity, UUID> {
}
@SpringBootTest
public class MyServiceIT {
@Autowired
MyService service;
@Test
void testSavingAndReading_positive() throws JsonProcessingException {
// prepare data
UUID uuid = UUID.randomUUID();
MyObject object1 = new MyObject();
object1.id = uuid;
MyObject object2 = new MyObject();
object2.id = uuid;
List<MyObject> objects = List.of(object1, object2);
// save data in database
MyEntity savedEntity = service.saveObjects(objects);
// read back
List<MyObject> result = service.readObjects(savedEntity.id);
// verify
assertEquals(2, result.size());
assertEquals(uuid, result.get(0).id);
assertEquals(uuid, result.get(1).id);
}
}
For reproducing this example you have to create a table in underlying database as
create table example (id uuid, objects text);
and provide database spec in application.yml like
spring:
datasource:
url: jdbc:postgresql://localhost:5432/postgres
username: postgres
password: ss