2013-07-02 3 views
2

У меня есть таблица Student с автоматически сгенерированным идентификатором в качестве первичного ключа и один-много сопоставлений с таблицей телефона.StackOverflowError on Hibernate Сохранить

Таблица «Мой телефон» содержит составной первичный ключ PhonePK с номером телефона и идентификатором внешнего ключа в таблице «Студент».

Если я только что сделал student.setPhones, и не делаю phonepk.setStudent, то жалобы на него: ID не может быть пустым. Поэтому я устанавливаю student.setPhones и phonePk.setStudent. Но теперь я получаю ошибку stackoverflow на toString.

Мне действительно не нравится устанавливать его в обоих направлениях, но не знаю, как обойти идентификатор не может быть пустой ошибкой. Я спрашивал много людей, но они не могли помочь. Может ли кто-нибудь взглянуть, пожалуйста?

Student.java

import java.io.Serializable; 
import java.util.Set; 

import javax.persistence.CascadeType; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.OneToMany; 

@Entity 
@SuppressWarnings("serial") 
public class Student implements Serializable { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private int id; 

private String fName; 

private String lName; 

private String mName; 

@OneToMany(cascade = CascadeType.ALL) 
@JoinColumn(name = "id") 
private Set<Phone> phones; 

/** 
* @return the fName 
*/ 
public String getfName() { 
    return fName; 
} 

/** 
* @return the id 
*/ 
public int getId() { 
    return id; 
} 

/** 
* @return the lName 
*/ 
public String getlName() { 
    return lName; 
} 

/** 
* @return the mName 
*/ 
public String getmName() { 
    return mName; 
} 

/** 
* @return the phones 
*/ 
public Set<Phone> getPhones() { 
    return phones; 
} 

/** 
* @param fName 
*   the fName to set 
*/ 
public void setfName(final String fName) { 
    this.fName = fName; 
} 

/** 
* @param id 
*   the id to set 
*/ 
public void setId(final int id) { 
    this.id = id; 
} 

/** 
* @param lName 
*   the lName to set 
*/ 
public void setlName(final String lName) { 
    this.lName = lName; 
} 

/** 
* @param mName 
*   the mName to set 
*/ 
public void setmName(final String mName) { 
    this.mName = mName; 
} 

/** 
* @param phones 
*   the phones to set 
*/ 
public void setPhones(final Set<Phone> phones) { 
    this.phones = phones; 
} 

/** 
* {@inheritDoc} 
*/ 
@Override 
public String toString() { 
    return String.format("Student [id=%s, fname=%s, lname=%s, mname=%s, phones=%s]",  
id, 
     fName, lName, mName, phones); 
} 

} 

Phone.java

import java.io.Serializable; 

import javax.persistence.EmbeddedId; 
import javax.persistence.Entity; 

@Entity 
@SuppressWarnings("serial") 
public class Phone implements Serializable { 

@EmbeddedId 
private PhonePK PK; 

private String color; 

/** 
* @return the color 
*/ 
public String getColor() { 
    return color; 
} 

public PhonePK getPK() { 
    return PK; 
} 

/** 
* @param color 
*   the color to set 
*/ 
public void setColor(final String color) { 
    this.color = color; 
} 

public void setPK(final PhonePK pK) { 
    PK = pK; 
} 

/** 
* {@inheritDoc} 
*/ 
@Override 
public String toString() { 
    return String.format("Phone [PK=%s, color=%s]", PK, color); 
} 

} 

PhonePK.java

import java.io.Serializable; 

import javax.persistence.Embeddable; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 

@Embeddable 
@SuppressWarnings({ "serial" }) 
public class PhonePK implements Serializable { 

@ManyToOne 
@JoinColumn(name = "id", insertable = false, updatable = false) 
private Student student; 

private String phoneNumber; 

public String getPhoneNumber() { 
    return phoneNumber; 
} 

public Student getStudent() { 
    return student; 
} 

public void setPhoneNumber(final String phoneNumber) { 
    this.phoneNumber = phoneNumber; 
} 

public void setStudent(final Student student) { 
    this.student = student; 
} 

/** 
* {@inheritDoc} 
*/ 
@Override 
public String toString() { 
    return String.format("PhonePK [student=%s, phoneNumber=%s]", student, phoneNumber); 
} 

} 

Main.java

import java.util.LinkedHashSet; 
import java.util.Set; 

import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.Transaction; 
import org.hibernate.cfg.Configuration; 

public class Main { 

public static void main(final String args[]) { 

    Configuration configuration = new Configuration(); 
    Transaction transaction = null; 

    configuration.addAnnotatedClass(Student.class); 
    configuration.addAnnotatedClass(Phone.class); 
    configuration.configure("hibernate.cfg.xml"); 
    SessionFactory sessionFactory = configuration.buildSessionFactory(); 
    Session session = sessionFactory.openSession(); 

    Student student = new Student(); 
    student.setfName("Bob"); 
    student.setlName("Buster"); 

    Set<Phone> phones = new LinkedHashSet<Phone>(); 
    Phone phone = new Phone(); 
    phone.setColor("Black"); 
    PhonePK phonePK = new PhonePK(); 
    phonePK.setPhoneNumber("1111111111"); 
    phonePK.setStudent(student); // Do not do this? But won't work (id cannot be null 
    error) if 
           // commented out?? 
    phone.setPK(phonePK); 
    phones.add(phone); 

    student.setPhones(phones); 

    try { 
     transaction = session.beginTransaction(); 
     System.out.println(student.toString()); // stackoverflow error! 
     session.save(student); 
     transaction.commit(); 
    } catch (HibernateException e) { 
     transaction.rollback(); 
     e.printStackTrace(); 
    } finally { 
     session.close(); 
    } 

} 
} 

ответ

2

Это происходит из-за того, как вы определили ToString() методы

Стьюдента toString() является применение телефона toString() который вызова PhonePK-х toString(), который в свою очередь, ссылаясь на Ученический toString() ... вызывает бесконечный цикл.


Давайте посмотрим, как это происходит в детально

В Студента toString() из phones переменной экземпляра в нем .it будет перебирать каждого телефона и позвоните по телефону toString()

public String toString() { 
    return String.format("Student [id=%s, fname=%s, lname=%s, mname=%s, phones=%s]",  
id, 
     fName, lName, mName, phones); 
} 



В телефоне toString() из-за PK переменной экземпляра в нем .it вызывается PhonePK toString()

public String toString() { 
    return String.format("Phone [PK=%s, color=%s]", PK, color); 
} 



В PhonePK toString() из phoneNumber переменной экземпляра в нем .it будет ссылаться на телефон toString()

public String toString() { 
    return String.format("PhonePK [student=%s, phoneNumber=%s]", student, phoneNumber); 
} 
+0

Хорошо, спасибо .. я исправил. Удалена переменная экземпляра студента из метода PhonePK toString. Но есть ли способ избежать круговой ссылки? Я не хочу делать student.setPhones и phone.setStudent оба. Не следует ли сдерживать уход за этим? – nomula

Смежные вопросы