Marzec
24
2009

JBoss Seam – relacje pomiędzy encjami

Słowa kluczowe: , , , | Kategorie: Seam Framework
No Gravatar

Omówiłem już adnotacje dotyczące encji, pozostawiając jednak temat relacji na później. Tym razem zajmę się właśnie tym zagadnieniem.

Podstawowe relacje, to te występujące pomiędzy dwiema encjami. Są to:

Postaram się wytłumaczyć na prostych przykładach ich działanie.

Jeden do jednego

Jest to najprostrza możliwa zależność dwóch encji. Oznacza, że jeden rekord tabeli A odpowiada maksymalnie jednemu rekordowi tabeli B. Relacja przechowywana jest w jednej z tabel:

CREATE TABLE "A"
(
  "id" bigint NOT NULL,
  CONSTRAINT "pk_a" PRIMARY KEY ("id")
);

CREATE TABLE "B"
(
  "id" bigint NOT NULL,
  "id_a" bigint,
  CONSTRAINT "pk_b" PRIMARY KEY ("id"),
  CONSTRAINT "fk_b_a" FOREIGN KEY ("id_a")
      REFERENCES "A" ("id") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE
);

W mapowaniu obiektowo-relacyjnym takie tabele będą przedstawiane za pomocą dwóch encji (dla uproszczenia użyję pól zamiast właściwości):

@Entity
public class A {
    @Id
    @GeneratedValue
    @NotNull
    protected Long id;
}

@Entity
public class B {
    @Id
    @GeneratedValue
    @NotNull
    protected Long id;

    @OneToOne
    @JoinColumn(
            name = "id_a",
            referencedColumnName = "id")
    protected A a;
}

Jak widać na powyższym przykładzie, mając obiekt klasy B można odwołać się bezpośrednio do powiązanego z nim obiektu klasy A. Ponieważ to tabela B przechowuje klucz obcy, ewentualne odwołanie odwrotne w klasie A wyglądałoby w następujący sposób:

@OneToOne(mappedBy = "a")
protected B b;

Jeden do wielu

Wykorzystane w poprzedniej relacji tabele mogą zostać również powiązane relacją wiele do wielu. Jednak wówczas kod programu będzie wyglądał w następujący sposób:

@Entity
public class A {
    @Id
    @GeneratedValue
    @NotNull
    protected Long id;

    @OneToMany(mappedBy = "a")
    protected Set<B> b;
}

@Entity
public class B {
    @Id
    @GeneratedValue
    @NotNull
    protected Long id;

    @ManyToOne
    @JoinColumn(
            name = "id_a",
            referencedColumnName = "id")
    protected A a;
}

Tym razem w klasie B zmianie uległa jedna adnotacja (OneToOne na ManyToOne). Natomiast klasa A posiada teraz dowiązanie OneToMany do zbioru obiektów klasy B.

Wiele do wielu

Dla relacji wiele do wielu trzeba już zdefiniować trzy tabele:

CREATE TABLE "A"
(
  "id" bigint NOT NULL,
  CONSTRAINT "pk_a" PRIMARY KEY ("id")
);

CREATE TABLE "B"
(
  "id" bigint NOT NULL,
  CONSTRAINT "pk_b" PRIMARY KEY ("id")
);

CREATE TABLE "A_B"
(
  "id_a" bigint,
  "id_b" bigint,
  CONSTRAINT "pk_a_b" PRIMARY KEY ("id_a", "id_b"),
  CONSTRAINT "fk_a_b_a" FOREIGN KEY ("id_a")
      REFERENCES "A" ("id") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT "fk_a_b_b" FOREIGN KEY ("id_b")
      REFERENCES "B" ("id") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE
);

Jednak wciąż wystarczą tylko dwie klasy encji:

@Entity
public class A {
    @Id
    @GeneratedValue
    @NotNull
    protected Long id;

    @ManyToMany(mappedBy = "a")
    protected Set<B> b;
}

@Entity
public class B {
    @Id
    @GeneratedValue
    @NotNull
    protected Long id;

    @ManyToMany
    @JoinTable(
            name="A_B",
            joinColumns=
                @JoinColumn(
                        name="id_b",
                        referencedColumnName="id"),
            inverseJoinColumns=
                @JoinColumn(
                        name="id_a",
                        referencedColumnName="id"))
    protected Set<A> a;
}

Definicje klas niewiele się zmieniły. Tym razem w obu encjach istnieje odwołanie do zbioru obiektów. Dodatkowo wprowadzona została adnotacja opisująca tabelę A_B, która realizuje relację w bazie danych.

Podsumowanie

Opisałem dzisiaj wszystkie możliwe relacje pomiędzy dwiema encjami. Ich mapowanie jest w znacznym stopniu uproszczone przez stosowanie adnotacji. Jednak w realnych projektach może też wystąpić konieczność modelowania relacji bardziej złożonych. Ale o tym następnym razem.

Napisz Komentarz

*