简体   繁体   中英

Persist PK Object with JPA (ManyToMany)

Please change title if you know a better one, because I really don't know how to express the problem.

I've got three classes:

@Entity
public class User {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 @Column(name = "id")
 private Integer id;

 @NotNull
 @Size(min = 1, max = 45)
 @Column(name = "name")
 private String name;

 @JoinTable(name = "usuer_has_contact", joinColumns = {
     @JoinColumn(name = "user_id", referencedColumnName = "id")}, inverseJoinColumns = {
     @JoinColumn(name = "contact_id", referencedColumnName = "id")})
 @ManyToMany(cascade = CascadeType.ALL)
 private List<Contato> contactList;

 //Getters and Setters

}

DB Table:
Table Name: User
Columns: id (int pk), name (varchar(45) not null).

@Entity
private class Contact {

 @EmbeddedId
 protected UserHasContact userHasContact;

 @NotNull
 @Size(min = 1, max = 45)
 @Column(name = "value")
 private String value;

 @ManyToMany(mappedBy = "contactList")
 private List<User> userList;

 //Getters and Setters

}

DB Table:
Table Name: Contact
Columns: id (int pk), value (varchar(45) not null).

@Embeddable
private class UserHasContact {

 @NotNull
 @Column(name = "id")
 private Integer id;

 //Getters and Setters

}

DB Table:
Table Name: UserHasContact
Columns: userId (int pk), contactId (int pk).

What I'm trying to do is, to persist everything when I persist the User itself. For example:

User user = new User();
user.setContactList(new ArrayList<Contact>());

Contact contact = new Contact();
contact.setValue("555-5555");

user.getContactList().add(contact);

// Here I'd call another class, passing User so it would only do a
// entityManager.persist(user), and it would persist it all and
// take care of all tables for me. What I don't want to do is to
// fill up the values myself, I want let JPA do it for me.

I expected to save after doing this, but it says contactId is null and it cannot be null. What can I do?

Why do you create an embeddable UserHasContact class to just store a single Integer? You're making it harder than necessary. Just use an Integer ID as the contact primary key. This however is not the cause of your problem.

You're trying to persist a user containing a contact in its list of contacts. Your contact's ID is not auto-generated, and you did not assign any ID to this contact ID. How could JPA save this contact in database? Moreover, you didn't persist the contact, so it's transient.

You must

  • either assign an ID tothe contact, or annotate its ID so that it's auto-generated
  • persist the contact as well as the user

Here's the code for the Contact entity:

@Entity
private class Contact {
 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY) // this makes the ID auto-generated
 @Column(name = "id")
 private Integer id;

 @NotNull
 @Size(min = 1, max = 45)
 @Column(name = "value")
 private String value;

 @ManyToMany(mappedBy = "contactList")
 private List<User> userList;

 //Getters and Setters
}

And in the code where the user and contact are created:

User user = new User();
user.setContactList(new ArrayList<Contact>());

entityManager.persist(user);

Contact contact = new Contact();
contact.setValue("555-5555");

entityManager.persist(contact);

user.getContactList().add(contact);
// you should also make sure that the object graph is consistent, so
// the following line should lso be added, (though not strictly necessary)
contact.getUserList().add(user);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM