Category Archives: Hibernate

Hibernate a jednosměrné one-to-many vztahy

Dnes nebudu psát nic světoborného. Jen bych uvedl na pravou míru chybu, které jsem se dopustil v minulém článku. Není pravda, že Hibernate neumí jednosměrné one-to-many vztahy bez použití join tabulky, naopak je to docela snadné.

Na svoji obhajobu mohu uvést jen to, že jsem to v době psaní článku moc neřešil a narazil jsem na dokumentaci, která naznačovala, že to není nijak moc jednoduché. A hlavně, abych nevypadal jako úplný blbec, ponořil jsem se do specifikace EJB 3.0. Tam jsem na straně 185 našel následující text

Unidirectional one-to-many relationships may be implemented using one-to-many foreign key mappings, however, such support is not required in this release. Applications that want to use a foreign key mapping strategy for one-to-many relationships should make these relationships bidirectional to ensure portability.

Takže se mohu vymlouvat, že jsem tu relaci udělal obousměrnou, abych zařídil přenositelnost.

Ale dost už bylo výmluv, podívejme se na to jak ono mapování zařídit. Připomenu jen, že vytváříme třídu Client, která obsahuje kolekci adres a účtů (viz. obrázek)

@Entity
@Table(name="client")
public class Client {

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

@Column
private String name;

@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name=“client_id”, nullable=false)
@BatchSize(size=10)
private Set<Account> accounts = new HashSet<Account>();

@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name=“client_id”, nullable=false)
@BatchSize(size=10)
private Set<Address> addresses = new HashSet<Address>();

public void addAddress(Address address)
{
addresses.add(address);
}
//zbytek vynechán
}

Všimněte si prosím anotace @JoinColumn(name=”client_id”, nullable=false), která nám zajistí požadované mapovaní přes cizí klíč. Důležitý je druhý atribut – nullable. Ten Hibernatu říká, že cizí klíč client_id v tabulce address nesmí obsahovat null.

Oproti minulé verzi vidíme značné zjednodušení. Nemusíme se starat o plnění druhého směru relace. Dokonce ani neuděláme stejnou chybu jako já minule, když jsem zapomněl vyřešit předávání adresy mezi klienty (automatické odebrání adresy jednomu klientovi, při přidání druhému). Abych to ještě více zjednodušil, použil jsem přehlednější, i když méně výkonnou, formu inicializace množiny adres.

Takže pro shrnutí, jednosměrná one-to-many relace v Hibernate funguje, nicméně není přenositelná v rámci EJB 3.0. Ještě bych chtěl na závěr poděkovat Markovi L. za to, že mě upozornil na spoustu chyb v minulém článku a ukázal mi, že by to mapování měl Hibernate přeci jenom umět.

Zdrojové kódy můžete stáhnout zde.

Zdroje:

  1. JSR 220: Enterprise JavaBeansTM,Version 3.0
  2. Hibernate dokumentace
  3. EJB 3.0 – still trying to catch up to JDO and Hibernate
  4. Getting Started with Hibernate