Adding a JPA Entity and its @OneToMany Children

We just covered how to update an Entity and its @OneToMany Children in Spring JPA. Now we’ll look at how to add a record and its multiple children. The source we’re using is found in the v0.1.0 branch of my Spring-Data Github App. Schema recap is Contacts with a @OneToMany Contact Phones and a @ManyToMany Contact Hobbies relationship. Here’s a sample record.

Starting with the ContactDTO

We’ll start by creating a simple ContactDTO data container for our Contact and its Phones. (We’re ignoring Hobbies for now.) You’ll notice we’re not entering a ContactId in the ContactDTO. We’re not entering a ContactId or ContactPhoneId in the ContactPhoneDTO records either. JPA will take care of that when the Contact is persisted and saved to the database.

Adding the Record in the Service Layer

Below is the code of our ContactService add() method. You’ll notice that we are using a Builder pattern to create the ContactPhone items where we assign the Contact. We save the ContactPhone objects individually in ContactPhoneRepository.

You’ll notice a EntityManager Refresh on the newly created Contact Entity. That is required to refresh the state of the Contact instance from the database, overwriting changes made to the entity. In our case we’re adding the ContactPhones to the Entity. Without performing a refresh() we’d get a NullPointerException when retrieving the Contact’s Phones.

@Transactional
@Override
public Contact add(ContactDTO added) {
	LOGGER.info("Adding new contact with information: {}", added);

	//Creates an instance of a Contact by using the builder pattern
	Contact contact = Contact.getBuilder(added.getFirstName(),
	                added.getLastName(), added.getEmail())
	        .birthDate(added.getBirthDate())
	        .build();

	Contact saved = contactRepository.save(contact);

	if (added.getContactPhones() != null) {
	    for (ContactPhoneDTO contactPhoneDTO : added.getContactPhones()) {
	        ContactPhone contactPhone = ContactPhone.getBuilder(saved,
	                contactPhoneDTO.getPhoneType(),
	                contactPhoneDTO.getPhoneNumber())
	                .build();

	        contactPhoneRepository.save(contactPhone);
	    }
	}
	em.refresh(saved);
	return saved;

}

Testing the New Contact and its Phones

Below are our tests to confirm the new Contact and its phones were added to the database.

1) We create a new contactDTO as we discussed. We recreate our H2 database on each Test run and know it contains 10 Contacts, so after adding the new Contact we know that the Contact just added exists as a viable Entity and that its ContactId is 11.

2) Going straight to the database for our ContactPhones with “11” as a ContactId, we confirm that we retrieve 2 ContactPhone records.

3) Now let’s confirm that the newly created Contact Entity contains our phones. As I mentioned earlier, without an Entity Refresh(Contact) after adding the ContactPhone @OneToMany records we’d get a NullPointerException here.

4) Our final test is to confirm that our new Contact Entity is part of The Collective when we perform a ContactService.findAll().