OneToMany дочерние объекты не сохраняются при сохранении () - PullRequest
1 голос
/ 22 октября 2019

Я сталкиваюсь со следующим поведением в спящем режиме, которое не могу объяснить, и я надеялся, что кто-то может дать объяснение того, что происходит.

У меня двунаправленная @OneToMany связь между Instructor и Course. Поскольку они имеют CascadeType.PERSIST, я ожидаю, что когда я создаю объект Course и связываю его с Instructor и наоборот, а затем вызываю метод .save() в инструкторе, оба объекта будут сохраняться в базе данных, хотяэто приводит к тому, что без курсов сохраняется только Instructor.

Если я вызываю метод persist() для ex: session.persist(instructor), то и преподаватель, и курсы сохраняются.

Здесьмои сущности и мой основной метод.

Инструктор:

@Entity
@Table(name = "instructor")
public class Instructor {

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

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "instructor_detail_id")
    private InstructorDetail instructorDetail;

    @OneToMany(mappedBy = "instructor", cascade = {CascadeType.DETACH,
    CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch = FetchType.LAZY)
    private List<Course> courses = new ArrayList<>();

    public Instructor() {
    }

    public Instructor(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    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 String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public InstructorDetail getInstructorDetail() {
        return instructorDetail;
    }

    public void setInstructorDetail(InstructorDetail instructorDetail) {
        this.instructorDetail = instructorDetail;
    }

    public List<Course> getCourses() {
        return courses;
    }

    public void setCourses(List<Course> courses) {
        this.courses = courses;
    }

    @Override
    public String toString() {
        return "Instructor{" +
            "id=" + id +
            ", firstName='" + firstName + '\'' +
            ", lastName='" + lastName + '\'' +
            ", email='" + email + '\'' +
            ", instructorDetail=" + instructorDetail +
            ", courses=" + courses +
            '}';
    }

    public void addCourse(Course course) {
        courses.add(course);
        course.setInstructor(this);
    }
}

Курс

@Entity
@Table(name = "course")
public class Course {

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

    @Column(name = "title")
    private String title;

    @ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE,
        CascadeType.PERSIST, CascadeType.REFRESH}, fetch = FetchType.LAZY)
    @JoinColumn(name = "instructor_id")
    private Instructor instructor;

    public Course(String title) {
        this.title = title;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Instructor getInstructor() {
        return instructor;
    }

    public void setInstructor(Instructor instructor) {
        this.instructor = instructor;
    }
}

Основной

public class Test {

    public static void main(String[] args) {

        //create session factory
        SessionFactory sessionFactory = new Configuration()
            .configure("com/ysoft/config/hibernate.cfg.xml")
            .addAnnotatedClass(Instructor.class)
            .addAnnotatedClass(InstructorDetail.class)
            .addAnnotatedClass(Course.class)
            .buildSessionFactory();

        //create session
        Session session = sessionFactory.getCurrentSession();

        try (sessionFactory) {
            session.beginTransaction();

            Instructor instructor = new Instructor("John", "Doe", "John.Doe@email.com");
            InstructorDetail instructorDetail = new InstructorDetail("http://www.something.com", "Coding");

            Course mathCourse = new Course("Math");
            Course englishCourse = new Course("English");
            Course sportsCourse = new Course("Sports");

            instructor.addCourse(mathCourse);
            instructor.addCourse(englishCourse);
            instructor.addCourse(sportsCourse);

            instructor.setInstructorDetail(instructorDetail);

            session.save(instructor);

            session.getTransaction().commit();

            System.out.println("Persisted" + instructor);
        }
    }
}

1 Ответ

1 голос
/ 22 октября 2019

Если я изменил @OneToMany каскадный массив на CascadeType.ALL, то это сработало - но я не знаю почему, поскольку соответствующие типы уже были там.

У дочерней стороны не должно быть каскадауказано - процитировать последние документы Hibernate:

Ассоциация @OneToMany по определению является родительской, даже если она однонаправленная или двунаправленная. Только родительская сторона ассоциации имеет смысл каскадно переходить из одного состояния объекта в другое.

Обновление:

Согласно this кажется, что он вызывает save() вместо использования JPA EntityManager.persist(), для этого также требуется специфичный для Hibernate каскадный тип SAVE_UPDATE. (Что несовместимо с определением JPA @OneToMany)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...