【问题标题】:Session.save throwing TransientObjectExceptionSession.save 抛出 TransientObjectException
【发布时间】:2018-08-13 10:00:32
【问题描述】:

我有两个实体,分别称为 studentcourse,具有 ManyToMany relationship。正如我在this 文章中所读到的,我们可以调用 save 方法来保存事务中的相关实体,或者一旦刷新会话,它将被保存。我也了解导致此异常的typical cascading problem,但在这里我也处理了它,但仍然我在调用 save 方法时收到 TransientObjectException,而 persist 方法工作得很好。有人可以解释一下这里发生了什么吗?

这是我的代码:

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

【问题讨论】:

  • 在保存之前尝试将学生添加到课程中
  • 试过了!!但现在Student对象出现相同的异常:线程“main”中的异常org.hibernate.TransientObjectException:对象引用了未保存的瞬态实例-在刷新之前保存瞬态实例:manytomany.demo.Student
  • 你试过在student之前保存course1course2吗?
  • 是的,我试过了,这样它工作正常,但它不应该在事务边界内自动保存相关实体而不等待我显式调用 save 吗?
  • Doc 说save() 在刷新事务时不会立即执行。这肯定是相关的

标签: java hibernate


【解决方案1】:

正如其他人建议的那样,您可以在所有相关实体上显式调用 session.save,或者您可以使用 Hibernate 特定 @Cascade 注释,如下所示。

@Cascade(CascadeType.SAVE_UPDATE)

在任何关联上使用cascade={CascadeType.ALL} 的警告是,一旦对父对象调用 delete,您将删除所有子对象(或表中的行)。所以要小心一点。

【讨论】:

    【解决方案2】:

    您已经为持久化和合并定义了级联模式,但为了保存,您必须声明 cascade=ALL 或手动保存相关实体:

    cascade=CascadeType.ALL

    【讨论】:

      【解决方案3】:

      你应该尝试而不是

      session.save()

      使用

      session.persist()

      【讨论】:

      • 我之前已经提到过,persist() 工作正常。我想知道为什么不保存()?
      • 我想我应该在问题中突出显示它...无论如何感谢您的回答:)
      【解决方案4】:

      试试这个,它对我有用

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

      【讨论】:

      • 我已经尝试过了,正如我在上面的 cmets 中提到的那样。
      • 在学生课程 courseList 字段中使用 cascade=CascadeType.ALL。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 1970-01-01
      • 2017-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多