I have a Client object that “owns” a number of Address objects. So, my Client class defines a set to hold the address objects as follows :
@OneToMany(fetch=FetchType.LAZY, mappedBy="client", cascade={CascadeType.ALL})
and my Address class defines a Client instance variable like this :
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="ClientId", nullable=false)
I have a form that allows the user to enter Client details and Address details at the same time, with the intention being that saving the form will cause the Client to be saved to the database, and the Cascade will cause the address to also be saved.
I can get this to work, but only if I manually set the Client property on the Address object in the controller immediately before I save the client object.
public String clientSave(@ModelAttribute("form") AddClientForm form, ModelMap model) {
logger.debug("clientsave");
Client client = form.getClient();
HashSet<Address> addresses = new HashSet<Address>(form.getAddresses());
// TODO - Should I have to do this?
for (Address a : addresses){
a.setClient(client);
}
client.setAddresses(addresses);
clientService.saveClient(client);
Should I need to do this, or am I missing something ?
Yes, you need to do this. Hibernate looks at the owner side of the association to persist it, and the owner side is the side which doesn’t have the
mappedByattribute.In general, you are responsible of the coherence of the object graph. It’s thus often a good idea to have a method
addAddress()in Customer which sets both sides of the association. YoursetAddresses()method could do that as well.