我有两个实体,分别是学生和课程,具有 ManyToMany relationship 。正如我在this文章中所读到的,我们可以调用save方法来保存事务中的相关实体,否则一旦刷新会话,它将被保存。我也了解导致此异常的typical cascading problem,但在这里我也对此进行了处理,但仍然在持久方法正常工作的同时,我在调用save方法时遇到了TransientObjectException 。有人可以解释一下这里发生了什么吗?
这是我的代码:
SaveVsPersistTest.java
public class SaveVsPersistTest {
public static void main(String[] args) {
// Create session factory object
SessionFactory sessionFactory = new Configuration()
.configure("hibernate.cfg.xml")
.addAnnotatedClass(Student.class)
.addAnnotatedClass(Course.class)
.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Student student = new Student("Gopal");
Course course1 = new Course("Java");
Course course2 = new Course("C++");
student.addCourse(course1);
student.addCourse(course2);
session.save(student);
transaction.commit();
session.flush();
}
}
Student.java
@Entity
@Table(name="student")
public class Student {
public Student() {
}
public Student(String name) {
super();
this.name = name;
}
@Id
@Column(name="student_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="student_name")
private String name;
@ManyToMany(cascade={CascadeType.DETACH,CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE})
@JoinTable(name="student_course",
joinColumns={@JoinColumn(name="student_id")},
inverseJoinColumns={@JoinColumn(name="course_id")})
private List<Course> courseList;
public void addCourse(Course tempcourse) {
if(courseList == null){
courseList= new ArrayList<>();
}
courseList.add(tempcourse);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getCourseList() {
return courseList;
}
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", courseList=" + courseList + "]";
}
}
Course.java
@Entity
@Table(name="course")
public class Course {
public Course() {
}
public Course(String courseTitle) {
super();
this.courseTitle = courseTitle;
}
@Id
@Column(name="course_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="course_title")
private String courseTitle;
@ManyToMany(cascade={CascadeType.DETACH,CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE})
@JoinTable(name="student_course",
joinColumns={@JoinColumn(name="course_id")},
inverseJoinColumns={@JoinColumn(name="student_id")})
private List<Student> StudentList;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCourseTitle() {
return courseTitle;
}
public void setCourseTitle(String courseTitle) {
this.courseTitle = courseTitle;
}
public List<Student> getStudentList() {
return StudentList;
}
public void setStudentList(List<Student> studentList) {
StudentList = studentList;
}
@Override
public String toString() {
return "Course [id=" + id + ", courseTitle=" + courseTitle + ", StudentList=" + StudentList + "]";
}
}
例外
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: manytomany.demo.Course
答案 0 :(得分:1)
您已经定义了用于持久和合并的级联模式,但是对于保存,您必须声明cascade = ALL或手动保存相关实体:
cascade=CascadeType.ALL
答案 1 :(得分:1)
根据其他建议,您可以显式调用所有相关实体上的session.save,也可以使用如下所示的特定于Hibernate的@Cascade注释。
@Cascade(CascadeType.SAVE_UPDATE)
在任何关联上使用cascade={CascadeType.ALL}
的警告是,一旦对父对象调用delete,则将删除所有子对象(或表中的行)。因此请谨慎一点。
答案 2 :(得分:0)
您应该尝试代替
session.save()
使用
session.persist()
答案 3 :(得分:0)
尝试一下,它对我有用
Student s = new Student();
s.setName("Gopal");
Course c1 = new Course();
c1.setCourseTitle("courseTitle1");
Course c2 = new Course();
c2.setCourseTitle("courseTitle2");
// adding courses to student entity
s. getCourseList().add(c1);
s. getCourseList().add(c2);
// adding a student to courses.
c1.getStudentList().add(s);
c2.getStudentList().add(s);
// saving all entities to DB.
session.save(s);
session.save(c1);
session.save(c2);
transaction.commit();
session.flush();