Reputation: 6579
I'm using Spring with Hibernate as a JPA provider and are trying to get a @OneToMany (a contact having many phonenumbers) to save the foreign key in the phone numbers table. From my form i get a Contact object that have a list of Phone(numbers) in it. The Contact get persisted properly (Hibernate fetches an PK from the specified sequence). The list of Phone(numbers) also gets persisted with a correct PK, but there's no FK to the Contacts table.
public class Contact implements Serializable {
@OneToMany(mappedBy = "contactId", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
private List<Phone> phoneList;
}
public class Phone implements Serializable {
@JoinColumn(name = "contact_id", referencedColumnName = "contact_id")
@ManyToOne
private Contact contactId;
}
@Repository("contactDao")
@Transactional(readOnly = true)
public class ContactDaoImpl implements ContactDao {
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void save(Contact c) {
em.persist(c);
em.flush();
}
}
@Controller
public class ContactController {
@RequestMapping(value = "/contact/new", method = RequestMethod.POST)
public ModelAndView newContact(Contact c) {
ModelAndView mv = new ModelAndView("contactForm");
contactDao.save(c);
mv.addObject("contact", c);
return mv;
}
}
Hopefully I got all of the relevant bits above, otherwise please let me know.
Upvotes: 22
Views: 52340
Reputation: 21
In JPA this helped me
contact.getPhoneList().forEach(pl -> pl.setContact(contact));
contactRepository.save(contact);
Upvotes: 0
Reputation: 1892
Try this sample:
@Entity
public class Contact {
@Id
private Long id;
@JoinColumn(name = "contactId")
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Phone> phones;
}
@Entity
public class Phone {
@Id
private Long id;
private Long contactId;
}
Upvotes: 0
Reputation: 3065
If you want your relationship unidirectional i.e. can navigate from Contact to Phone's only, you need to add
@JoinColumn(name = "contact_id", nullable = false)
Under your @OneToMany
on your parent entity.
nullable = false
IS VITAL if you want hibernate to populate the fk on the child table
Upvotes: 1
Reputation: 625017
You have to manage the Java relationships yourself. For this kind of thing you need something like:
@Entity
public class Contact {
@Id
private Long id;
@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "contact")
private List<Phone> phoneNumbers;
public void addPhone(PhoneNumber phone) {
if (phone != null) {
if (phoneNumbers == null) {
phoneNumbers = new ArrayList<Phone>();
}
phoneNumbers.add(phone);
phone.setContact(this);
}
}
...
}
@Entity
public class Phone {
@Id
private Long id;
@ManyToOne
private Contact contact;
...
}
Upvotes: 31
Reputation: 21
I don't think the addPhone method is necessary, you only have to set the contact in the phone object:
phone.setContact(contact);
Upvotes: 2
Reputation: 137
If the Contact-Phone relationship is unidirectional, you can also replace mappedBy
in @OneToMany
annotation with @JoinColumn(name = "contact_id")
.
@Entity
public class Contact {
@Id
private Long id;
@OneToMany(cascade = CascadeType.PERSIST)
@JoinColumn(name = "contact_id")
private List<Phone> phoneNumbers;
// normal getter/setter
...
}
@Entity
public class PhoneNumber {
@Id
private Long id;
...
}
Similar in JPA @OneToMany -> Parent - Child Reference (Foreign Key)
Upvotes: 5
Reputation: 8722
In reply to Cletus' answer. I would say that it's important to have the @column
annotation on the id fields, as well as all the sequence stuff. An alternative to using the mappedBy parameter of the @OneToMany
annotation is to use the @JoinColumn
annotation.
As a kinda aside your implementation of addPhone needs looking at. It should probably be something like.
public void addPhone(PhoneNumber phone) {
if (phone == null) {
return;
} else {
if (phoneNumbers == null) {
phoneNumbers = new ArrayList<Phone>();
}
phoneNumbers.add(phone);
phone.setContact(this);
}
}
Upvotes: 6