Adnotacja @ElementCollection czy @OneToMany?

Adnotacja @ElementCollection czy @OneToMany?

Zacznijmy od adnotacji @ElementCollection. Adnotacja ta to jedna z adnotacji z pakietu:

import javax.persistence.*;

która pozwala szybko zmapować kolekcje danych.

Utwórzmy tabelę:

create table subject (
  id integer generated by default as identity,
  name varchar(255),
  subject_id integer,
  primary key (id)
)

Oraz mapowanie klasy jako obiektu wbudowanego z użyciem adnotacji @Embeddable:

@Embeddable
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Subject {
    private String name;
}

Klasa obiektu wbudowanego musi być oznaczona adnotacją @Embeddable. Nie oznacza się jej jako encji, tym bardziej nie określa się dla niej tabeli w bazie danych ani identyfikatora.

  • Klasa Teacher – każdy nauczyciel może prowadzić wiele przedmiotów:
@Entity
@Data
@NoArgsConstructor
public class Teacher {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;
 
    String name;
 
    public Teacher(String name) {
        this.name = name;
    }
 
    @ElementCollection
    @CollectionTable(
            name = "subject",joinColumns = @JoinColumn(name="id")
    )
    Set<Subject> subjects = new HashSet<>();
}

Oznaczenie kolekcji obiektów subjects adnotacjami:

@ElementCollection
@CollectionTable(name = "subject",joinColumns = @JoinColumn(name="id"))

pozwala szybko i w prosty sposób zmapować tabelę Subject na kolekcje obiektów typu Subject. Klasa Subject to nie jest jednak encja zarządzana przez Hibernate co oznacza, że nie ma możliwości operowania na jej obiektach tak jak w przypadku klas oznaczonych adnotacją @Entity. Operacje bazodanowe na obiektach klasy Subject możliwe są tylko i wyłącznie z użyciem klasy nadrzędnej – Teacher która jest encją zarządzana przez Hibernate.

Relacja @OneToMany wyglądałaby następująco:

  • Klasa Teacher:
@Entity
@Data
@NoArgsConstructor
public class Teacher {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;
 
    String name;
 
    public Teacher(String name) {
        this.name = name;
    }
 
    @OneToMany(mappedBy = "teacher")
    Set<Subject> subjects = new HashSet<>();
}
  • klasa Subject:
@Entity
@Data
@NoArgsConstructor
public class Subject {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;
 
    String name;
 
    @ManyToOne
    @JoinColumn(name="subject_id", nullable=false)
    Teacher teacher;
}

Takie mapowanie pozwala zarządzać encją Subject w sposób niezależny od encji nadrzędnej.

Zobacz kod na GitHubie i zapisz się na bezpłatny newsletter!

.

Leave a comment

Your email address will not be published.


*