Cześć, potrzebuję pomocy. Dalej ćwiczę sobie relacje pomiędzy tabelami i znów utknąłem. Pisze sobie prosty program - listę kontaktów. Składa się z trzech encji: "Contact", "Email" i "Group". Encja "Contact" jest główną encją, która jest związana relacją jeden-do-jeden z encją "Email" oraz relacja jeden do wielu z encją "Group" (każdy kontakt może być przypisany do wielu grup typu praca, rodzina etc.) "Contact" jest główną encją, pozostałe nie mają bez niej sensu, dlatego stwierdziłem, że najsensowniej będzie zapisać wszystkie pozostałe encje do bazy kaskadowo przy okazji zapisu encji głównej. Niestety program się wywala właśnie przy próbie zapisu tej encji. Dostaję taki komunikat:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: domain.Group
Wygląda mi to tak, jakby kaskada nie zadziałała, tylko nie rozumiem dlaczego...
Wklejam fragmenty kodu, które wydają mi się najważniejsze, gdyby to nie było wystarczająco czytelne to wrzucę na githuba, żeby tutaj tematu nie zaśmiecać.
Encje:
package domain;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "contacts")
public class Contact {
@Id
@GeneratedValue
private int contactId;
private String firstName;
private String lastName;
@OneToOne(targetEntity = Email.class,
cascade = CascadeType.ALL)
private Email email;
@ManyToMany(targetEntity = Group.class,
cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Group> groups = new ArrayList<Group>();
// Constructor
public Contact(){}
public Contact(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return "Contact{" +
"contactId=" + contactId +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email=" + email +
", groups=" + groups +
'}';
}
// Getters and Setters
public int getContactId() {
return contactId;
}
public void setContactId(int contactId) {
this.contactId = contactId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
public List<Group> getGroups() {
return groups;
}
public void setGroups(List<Group> groups) {
this.groups = groups;
}
}
package domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "emails")
public class Email {
@Id
@GeneratedValue
private int emailId;
private String email;
// Constructor
public Email(String email) {
this.email = email;
}
// Getters and Setters
public int getEmailId() {
return emailId;
}
public void setEmailId(int emailId) {
this.emailId = emailId;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
package domain;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "groups")
public class Group {
@Id
@GeneratedValue
private int groupId;
private String groupName;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Contact> contacts = new ArrayList<Contact>();
// Constructors
public Group(){}
public Group(String groupName) {
this.groupName = groupName;
}
@Override
public String toString() {
return "Group{" +
"groupId=" + groupId +
", groupName='" + groupName + '\'' +
", contacts=" + contacts +
'}';
}
// Getters and Setters
public int getGroupId() {
return groupId;
}
public void setGroupId(int groupId) {
this.groupId = groupId;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public List<Contact> getContacts() {
return contacts;
}
public void setContacts(List<Contact> contacts) {
this.contacts = contacts;
}
}
Fragment repozytorium:
public static void addNewContact(Contact contact){
Session session = null;
try {
session = HibernateUtils.openSession();
session.getTransaction().begin();
session.saveOrUpdate(contact);
session.getTransaction().commit();
}catch (Exception e) {
e.printStackTrace();
}finally {
if (session != null && session.isOpen()) {
session.close();
}
}
}
Metoda, która tworzy cały wpis do bazy:
public void addNewContact(){
System.out.println("Add New Contact");
System.out.println("===============");
System.out.println("");
System.out.println("First Name: ");
String firstName = scanner.next();
System.out.println("Last Name: ");
String lastName = scanner.next();
Contact contact = new Contact(firstName, lastName);
System.out.println("Email: ");
String email_ = scanner.next();
Email email = new Email(email_);
contact.setEmail(email);
boolean groupRun = true;
do{
System.out.println("Group name: ");
String groupName = scanner.next();
Group group = new Group(groupName);
contact.getGroups().add(group);
group.getContacts().add(contact);
System.out.println("Would you like to add another group? y/n");
String choice = scanner.next();
switch (choice.charAt(0)){
case 'y':
break;
case 'n':
groupRun = false;
break;
}
}while(groupRun);
ContactRepository.addNewContact(contact);
}
scibi92