Как именно работает аннотация Hibernate @OneToMany?

Я новичок в Hibernate и изучаю его в учебнике. У меня есть некоторые проблемы с пониманием того, как именно работает аннотация OneToMany.

Итак, у меня есть два класса сущностей: Student, который представляет студента, и Guide, который представляет человека, который направляет студента. Таким образом, каждый студент связан с одним гидом, но один гид может следовать за более чем одним студентом. Я хочу, чтобы руководство знало студентов, связанных с ним.

Так что я:

Студент:

@Entity
public class Student {

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

    @Column(name="enrollment_id", nullable=false)
    private String enrollmentId;    

    private String name;

    @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
    @JoinColumn(name="guide_id")
    private Guide guide;

    public Student() {}
    public Student(String enrollmentId, String name, Guide guide) {
        this.enrollmentId = enrollmentId;
        this.name = name;
        this.guide = guide;
    }

    public Guide getGuide() {
        return guide;
    }
    public void setGuide(Guide guide) {
        this.guide = guide;
    }

}

Итак, аннотация @ManyToOne в поле руководства:

@ManyToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
@JoinColumn(name="guide_id")
private Guide guide; 

означает, что один гид связан с одним студентом, но гид может следовать за многими студентами. Это правильно? Что именно делают указанные параметры каскада? Я думаю, это означает, что когда я сохраняю объект Student, который содержит объект Guide в качестве поля, этот объект Guide также автоматически сохраняется. И то же самое происходит, когда я удаляю объект Студент, соответствующая запись Руководство удаляется... но я не совсем в этом уверен...

Хорошо, если я сделаю это таким образом, у меня будет однонаправленная связь между записью в таблице Student и записью в таблице Guide, потому что в таблица Student. У меня будет внешний ключ для присоединения к таблице Guide, чтобы учащийся мог знать своего путеводителя, но, делая это таким образом, путеводитель не может знать следующего учащегося ...и это не умно.

Для этого класс Guide реализован следующим образом:

@Entity
public class Guide {

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

    @Column(name="staff_id", nullable=false)
    private String staffId; 

    private String name;
    private Integer salary;

    @OneToMany(mappedBy="guide", cascade={CascadeType.PERSIST})
    private Set<Student> students = new HashSet<Student>(); 

    public Guide() {}
    public Guide(String staffId, String name, Integer salary) {
        this.staffId = staffId;
        this.name = name;
        this.salary = salary;
    }

    public Set<Student> getStudents() {
        return students;
    }   
    public void setSalary(Integer salary) {
        this.salary = salary;
    }

    public void addStudent(Student student) {
        students.add(student);
        student.setGuide(this);
    }

}   

Итак, как видите, этот класс содержит:

@OneToMany(mappedBy="guide", cascade={CascadeType.PERSIST})
private Set<Student> students = new HashSet<Student>(); 

что он используется для объявления двунаправленной связи.

Поэтому мне кажется, что эта аннотация автоматически создает поле guide_id в таблице Student, которое представляет внешний ключ, реализующий двунаправленное отношение.

На самом деле, используя это сопоставление, таблица Student автоматически создается в моей базе данных следующим образом:

'id', 'bigint(20)', 'NO', 'PRI', NULL, 'auto_increment'
'enrollment_id', 'varchar(255)', 'NO', '', NULL, ''
'name', 'varchar(255)', 'YES', '', NULL, ''
'guide_id', 'bigint(20)', 'YES', 'MUL', NULL, ''

Поэтому в классе сущностей Student я не определил поле guide_id, но оно есть в таблице Student в базе данных. Поэтому я думаю, что создание этого поля в таблице зависит от предыдущей аннотации @OneToMany, определенной в классе сущности Guide. Это правильно или я что-то упускаю?


person AndreaNobili    schedule 10.07.2015    source источник


Ответы (1)


Да, вы можете определить сущность @OneToMany без двунаправленной ассоциации, а добавленный столбец находится на стороне сущности Many в базе данных (даже если сущность не знает, что она связана с сущностью One).

Вы также можете использовать для этого таблицу соединений, но это не обязательно.

person Kayaman    schedule 10.07.2015