Java 休眠保存时堆栈溢出错误

Java 休眠保存时堆栈溢出错误,java,hibernate,one-to-many,composite-key,stack-overflow,Java,Hibernate,One To Many,Composite Key,Stack Overflow,我有一个学生表,自动生成的id作为主键,并且一对多映射到电话表 My Phone表有一个复合主键PhonePK,其中包含学生表的电话号码和外键id 如果我只做student.setPhones而不做phonepk.setStudent,它对id的抱怨不能为null。所以我正在设置student.setPhones和phonePk.setStudent。但是现在我在toString上得到了一个stackoverflow错误 我真的不喜欢在一开始就设置为两种方式,但不知道如何绕过id不能为null的

我有一个学生表,自动生成的id作为主键,并且一对多映射到电话表

My Phone表有一个复合主键PhonePK,其中包含学生表的电话号码和外键id

如果我只做student.setPhones而不做phonepk.setStudent,它对id的抱怨不能为null。所以我正在设置student.setPhones和phonePk.setStudent。但是现在我在toString上得到了一个stackoverflow错误

我真的不喜欢在一开始就设置为两种方式,但不知道如何绕过id不能为null的错误。我问了很多人,但他们帮不上忙。谁能看一下吗

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);
}

}
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);
}

}
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);
}

}
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();
    }

}
}
PhonePK.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);
}

}
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);
}

}
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);
}

}
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();
    }

}
}
Main.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);
}

}
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);
}

}
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);
}

}
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();
    }

}
}
import java.util.LinkedHashSet;
导入java.util.Set;
导入org.hibernate.hibernateeexception;
导入org.hibernate.Session;
导入org.hibernate.SessionFactory;
导入org.hibernate.Transaction;
导入org.hibernate.cfg.Configuration;
公共班机{
公共静态void main(最终字符串参数[]){
配置=新配置();
事务=空;
配置.addAnnotatedClass(Student.class);
configuration.addAnnotatedClass(Phone.class);
configure(“hibernate.cfg.xml”);
SessionFactory SessionFactory=configuration.buildSessionFactory();
Session Session=sessionFactory.openSession();
学生=新生();
student.setfName(“Bob”);
student.setlName(“Buster”);
Set phones=new LinkedHashSet();
电话=新电话();
手机。设置颜色(“黑色”);
PhonePK PhonePK=新的PhonePK();
电话号码(“1111111”);
phonePK.setStudent(student);//不这样做?但不起作用(id不能为null
错误)如果
//注释掉??
phone.setPK(phonePK);
电话。添加(电话);
学生电话;
试一试{
事务=session.beginTransaction();
System.out.println(student.toString());//堆栈溢出错误!
保存(学生);
commit();
}捕获(休眠异常e){
transaction.rollback();
e、 printStackTrace();
}最后{
session.close();
}
}
}

这是因为您定义toString()方法的方式

学生的
toString()
正在调用Phone的
toString()
,后者正在调用PhonePK的
toString()
,后者反过来调用学生的
toString()
…导致无限循环。


让我们详细看看它是如何发生的

在Student
toString()
中,因为其中包含
phones
实例变量。它将遍历每个电话并调用电话
toString()



在Phone
toString()
中,因为其中的
PK
实例变量。它将调用PhonePK
toString()



在PhonePK
toString()
中,因为其中的
phoneNumber
实例变量。它将调用Phone
toString()


好的,谢谢。。我纠正了它。已从PhonePK toString方法中删除学生实例变量。但是有没有一种方法可以避免循环引用?我不想同时做student.setPhones和phone.setStudent。hibernate不应该处理这个吗?