You are on page 1of 24

CHAPTER 11

Entity Relationships

&KDSWHU FRYHUHG EDVLF SHUVLVWHQFH PDSSLQJV LQFOXGLQJ YDULRXV ZD\V WR GHILQH SUL
PDU\ NH\V DV ZHOO DV VLPSOH DQG FRPSOH[ SURSHUW\ W\SH PDSSLQJV 7KLV FKDSWHU UHWRROV
RXU HPSOR\HH UHJLVWU\ D ELW IXUWKHU E\ GLVFXVVLQJ WKH UHODWLRQVKLSV EHWZHHQ HQWLWLHV
,Q RUGHU WR PRGHO UHDO ZRUOG EXVLQHVV FRQFHSWV HQWLW\ EHDQV PXVW EH FDSDEOH RI IRUPLQJ
UHODWLRQVKLSV )RU LQVWDQFH DQ HPSOR\HH PD\ KDYH DQ DGGUHVV ZH¦G OLNH WR IRUP DQ
DVVRFLDWLRQ EHWZHHQ WKH WZR LQ RXU GDWDEDVH PRGHO 7KH DGGUHVV FRXOG EH TXHULHG DQG
FDFKHG OLNH DQ\ RWKHU HQWLW\ \HW D FORVH UHODWLRQVKLS ZRXOG EH IRUJHG ZLWK WKH
Employee HQWLW\ (QWLW\ EHDQV FDQ DOVR KDYH RQH WR PDQ\ PDQ\ WR RQH DQG PDQ\ WR
PDQ\ UHODWLRQVKLSV )RU H[DPSOH WKH Employee HQWLW\ PD\ KDYH PDQ\ SKRQH QXPEHUV
EXW HDFK SKRQH QXPEHU EHORQJV WR RQO\ RQH HPSOR\HH D RQH WR PDQ\ UHODWLRQVKLS
6LPLODUO\ DQ HPSOR\HH PD\ EHORQJ WR PDQ\ WHDPV ZLWKLQ KLV RU KHU RUJDQL]DWLRQ DQG
WHDPV PD\ KDYH DQ\ QXPEHU RI HPSOR\HHV D PDQ\ WR PDQ\ UHODWLRQVKLS

The Seven Relationship Types


6HYHQ W\SHV RI UHODWLRQVKLSV FDQ H[LVW EHWZHHQ HQWLW\ EHDQV 7KHUH DUH IRXU W\SHV RI
FDUGLQDOLW\ RQH WR RQH RQH WR PDQ\ PDQ\ WR RQH DQG PDQ\ WR PDQ\ ,Q DGGLWLRQ
HDFK UHODWLRQVKLS FDQ EH HLWKHU XQLGLUHFWLRQDO RU ELGLUHFWLRQDO 7KHVH RSWLRQV VHHP WR
\LHOG HLJKW SRVVLELOLWLHV EXW LI \RX WKLQN DERXW LW \RX¦OO UHDOL]H WKDW RQH WR PDQ\ DQG
PDQ\ WR RQH ELGLUHFWLRQDO UHODWLRQVKLSV DUH DFWXDOO\ WKH VDPH WKLQJ 7KXV WKHUH DUH
RQO\ VHYHQ GLVWLQFW UHODWLRQVKLS W\SHV 7R XQGHUVWDQG UHODWLRQVKLSV LW KHOSV WR WKLQN
DERXW VRPH VLPSOH H[DPSOHV
2QH WR RQH XQLGLUHFWLRQDO
7KH UHODWLRQVKLS EHWZHHQ DQ HPSOR\HH DQG DQ DGGUHVV <RX FOHDUO\ ZDQW WR EH DEOH
WR ORRN XS DQ HPSOR\HH¦V DGGUHVV EXW \RX SUREDEO\ GRQ¦W FDUH DERXW ORRNLQJ XS
DQ DGGUHVV¦V HPSOR\HH
2QH WR RQH ELGLUHFWLRQDO
7KH UHODWLRQVKLS EHWZHHQ DQ HPSOR\HH DQG D FRPSXWHU *LYHQ DQ HPSOR\HH ZH¦OO
QHHG WR EH DEOH WR ORRN XS WKH FRPSXWHU ,' IRU WUDFLQJ SXUSRVHV $VVXPLQJ WKH

171
FRPSXWHU LV LQ WKH WHFK GHSDUWPHQW IRU VHUYLFLQJ LW¦V DOVR KHOSIXO WR ORFDWH WKH
HPSOR\HH ZKHQ DOO ZRUN LV FRPSOHWHG
2QH WR PDQ\ XQLGLUHFWLRQDO
7KH UHODWLRQVKLS EHWZHHQ DQ HPSOR\HH DQG D SKRQH QXPEHU $Q HPSOR\HH FDQ
KDYH PDQ\ SKRQH QXPEHUV EXVLQHVV KRPH FHOO HWF <RX PLJKW QHHG WR ORRN XS
DQ HPSOR\HH¦V SKRQH QXPEHU EXW \RX SUREDEO\ ZRXOGQ¦W XVH RQH RI WKRVH QXP
EHUV WR ORRN XS WKH HPSOR\HH
2QH WR PDQ\ ELGLUHFWLRQDO
7KH UHODWLRQVKLS EHWZHHQ DQ HPSOR\HH PDQDJHU DQG GLUHFW UHSRUWV *LYHQ D PDQ
DJHU ZH¦G OLNH WR NQRZ ZKR¦V ZRUNLQJ XQGHU KLP RU KHU 6LPLODUO\ ZH¦G OLNH WR EH
DEOH WR ILQG WKH PDQDJHU IRU D JLYHQ HPSOR\HH 1RWH WKDW D PDQ\ WR RQH ELGLUHF
WLRQDO UHODWLRQVKLS LV MXVW DQRWKHU SHUVSHFWLYH RQ WKH VDPH FRQFHSW
0DQ\ WR RQH XQLGLUHFWLRQDO
7KH UHODWLRQVKLS EHWZHHQ D FXVWRPHU DQG KLV RU KHU SULPDU\ HPSOR\HH FRQWDFW
*LYHQ D FXVWRPHU ZH¦G OLNH WR NQRZ ZKR¦V LQ FKDUJH RI KDQGOLQJ WKH DFFRXQW ,W
PLJKW EH OHVV XVHIXO WR ORRN XS DOO WKH DFFRXQWV D VSHFLILF HPSOR\HH LV IURQWLQJ
DOWKRXJK LI \RX ZDQW WKLV FDSDELOLW\ \RX FDQ LPSOHPHQW D PDQ\ WR RQH ELGLUHFWLRQDO
UHODWLRQVKLS
0DQ\ WR PDQ\ XQLGLUHFWLRQDO
7KH UHODWLRQVKLS EHWZHHQ HPSOR\HHV DQG WDVNV WR EH FRPSOHWHG (DFK WDVN PD\ EH
DVVLJQHG WR D QXPEHU RI HPSOR\HHV DQG HPSOR\HHV PD\ EH UHVSRQVLEOH IRU PDQ\
WDVNV )RU QRZ ZH¦OO DVVXPH WKDW JLYHQ D WDVN ZH QHHG WR ILQG LWV UHODWHG HPSOR\HHV
EXW QRW WKH RWKHU ZD\ DURXQG ,I \RX WKLQN \RX QHHG WR GR VR LPSOHPHQW LW DV D
ELGLUHFWLRQDO UHODWLRQVKLS
0DQ\ WR PDQ\ ELGLUHFWLRQDO
7KH UHODWLRQVKLS EHWZHHQ DQ HPSOR\HH DQG WKH WHDPV WR ZKLFK KH RU VKH EHORQJV
7HDPV PD\ DOVR KDYH PDQ\ HPSOR\HHV DQG ZH¦G OLNH WR GR ORRNXSV LQ ERWK
GLUHFWLRQV
1RWH WKDW WKHVH UHODWLRQV UHSUHVHQW WKH QDYLJDELOLW\ RI \RXU GRPDLQ PRGHO 8VLQJ -3$
4/ RU WKH &ULWHULD $3, FRYHUHG LQ &KDSWHU \RX¦OO EH DEOH WR UHWXUQ HYHQ DQ XQ
PDSSHG DVVRFLDWLRQ IRU H[DPSOH UHWXUQ WKH WDVNV IRU D JLYHQ HPSOR\HH HYHQ LI WKH
DVVRFLDWLRQ KDV EHHQ PDSSHG DV PDQ\ WR RQH XQLGLUHFWLRQDO 2QFH DJDLQ WKH DVVRFL
DWLRQV GHILQHG LQ WKH PHWDGDWD UHSUHVHQW WKH GRPDLQ REMHFW QDYLJDWLRQ RQO\
,Q WKLV FKDSWHU ZH GLVFXVV KRZ WR VSHFLI\ UHODWLRQVKLSV E\ DSSO\LQJ DQQRWDWLRQV WR \RXU
UHODWHG HQWLW\ EHDQV :H DOVR GLVFXVV VHYHUDO GLIIHUHQW FRPPRQ GDWDEDVH VFKHPDV DQG
\RX ZLOO OHDUQ KRZ WR PDS WKHP WR \RXU DQQRWDWHG UHODWLRQVKLSV

172 | Chapter 11:—Entity Relationships


One-to-One Unidirectional Relationship
$Q H[DPSOH RI D RQH WR RQH XQLGLUHFWLRQDO UHODWLRQVKLS LV RQH EHWZHHQ RXU Employee
HQWLW\ DQG DQ Address ,Q WKLV LQVWDQFH HDFK HPSOR\HH KDV H[DFWO\ RQH DGGUHVV DQG
HDFK DGGUHVV KDV H[DFWO\ RQH HPSOR\HH :KLFK EHDQ UHIHUHQFHV ZKLFK GHWHUPLQHV WKH
GLUHFWLRQ RI QDYLJDWLRQ :KLOH WKH Employee KDV D UHIHUHQFH WR WKH Address WKH
Address GRHVQ¦W UHIHUHQFH WKH Employee 7KH UHODWLRQVKLS LV WKHUHIRUH XQLGLUHFWLRQDO
\RX FDQ RQO\ JR IURP WKH HPSOR\HH WR WKH DGGUHVV QRW WKH RWKHU ZD\ DURXQG WKURXJK
REMHFW QDYLJDWLRQ ,Q RWKHU ZRUGV DQ Address HQWLW\ KDV QR LGHD ZKR RZQV LW
)LJXUH VKRZV WKLV UHODWLRQVKLS

)LJXUH 2QH WR RQH XQLGLUHFWLRQDO UHODWLRQVKLS

Relational database schema


2QH WR RQH XQLGLUHFWLRQDO UHODWLRQVKLSV QRUPDOO\ XVH D IDLUO\ W\SLFDO UHODWLRQDO GDWDEDVH
VFKHPD LQ ZKLFK RQH WDEOH FRQWDLQV D IRUHLJQ NH\ SRLQWHU WR DQRWKHU WDEOH ,Q WKLV
FDVH WKH Employee WDEOH FRQWDLQV D IRUHLJQ NH\ WR WKH Address WDEOH EXW WKH Address
WDEOH GRHVQ¦W FRQWDLQ D IRUHLJQ NH\ WR WKH Employee WDEOH 7KLV DOORZV UHFRUGV LQ WKH
Address WDEOH WR EH VKDUHG E\ RWKHU WDEOHV D VFHQDULR H[SORUHG LQ £0DQ\ WR 0DQ\ 8QL
GLUHFWLRQDO 5HODWLRQVKLS¤ RQ SDJH

Programming model
,Q XQLGLUHFWLRQDO UHODWLRQVKLSV QDYLJDWHG RQO\ RQH ZD\ RQH RI WKH HQWLW\ EHDQV GHILQHV
D SURSHUW\ WKDW OHWV LW JHW RU VHW WKH RWKHU EHDQ LQ WKH UHODWLRQVKLS 7KXV LQVLGH WKH
Employee FODVV \RX FDQ FDOO WKH getAddress() setAddress() PHWKRGV WR DFFHVV WKH $G
GUHVV HQWLW\ EXW WKHUH DUH QR PHWKRGV LQVLGH WKH Address FODVV WR DFFHVV WKH Employee
/HW¦V ORRN DW KRZ ZH ZRXOG PDUN XS WKH Employee EHDQ FODVV WR LPSOHPHQW WKLV RQH WR
RQH UHODWLRQVKLS WR Address
/**
* The employee's address
*/
@OneToOne
@JoinColumn(name="ADDRESS_ID")
// Unidirectional relationship
private Address address;

The Seven Relationship Types | 173


$ RQH WR RQH UHODWLRQVKLS LV VSHFLILHG XVLQJ WKH @javax.persistence.OneToOne DQQRWD
WLRQ DQG LV PDSSHG ZLWK WKH @javax.persistence.JoinColumn DQQRWDWLRQ /HW¦V ILUVW
ORRN DW WKH @JoinColumn DQQRWDWLRQ
package javax.persistence;

@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface JoinColumn
{
String name() default "";
String referencedColumnName() default "";
boolean unique() default false;
boolean nullable() default true;
boolean insertable() default true;
boolean updatable() default true;
String columnDefinition() default "";
String table() default "";
}

7KH @JoinColumn DQQRWDWLRQ LV DQDORJRXV WR WKH @Column DQQRWDWLRQ ,W GHILQHV WKH


FROXPQ LQ WKH Employee¦V WDEOH WKDW UHIHUHQFHV WKH SULPDU\ NH\ RI WKH Address WDEOH LQ
WKH VFKHPD ,I \RX DUH MRLQLQJ RQ VRPHWKLQJ RWKHU WKDQ WKH SULPDU\ NH\ FROXPQ RI WKH
Address WDEOH WKHQ \RX PXVW XVH WKH referencedColumnName() DWWULEXWH 7KLV
referencedColumnName() PXVW EH XQLTXH VLQFH WKLV LV D RQH WR RQH UHODWLRQVKLS
,I \RX QHHG WR PDS D RQH WR RQH UHODWLRQVKLS LQ ZKLFK WKH UHODWHG HQWLW\ KDV D FRPSRVLWH
SULPDU\ NH\ XVH WKH @JoinColumns DQQRWDWLRQ WR GHILQH PXOWLSOH IRUHLJQ NH\ FROXPQV
public @interface @JoinColumns
{
JoinColumn[] value();
}

1RZ OHW¦V OHDUQ DERXW WKH @OneToOne DQQRWDWLRQ


package javax.persistence;

@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OneToOne
{
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;
boolean optional() default true;
String mappedBy() default "";
boolean orphanRemoval() default false;
}

7KH targetEntity() DWWULEXWH UHSUHVHQWV WKH HQWLW\ FODVV \RX KDYH D UHODWLRQVKLS WR
8VXDOO\ \RX GR QRW KDYH WR LQLWLDOL]H WKLV DWWULEXWH DV WKH SHUVLVWHQFH SURYLGHU FDQ
ILJXUH RXW WKH UHODWLRQVKLS \RX DUH VHWWLQJ XS IURP WKH SURSHUW\¦V W\SH

174 | Chapter 11:—Entity Relationships


7KH fetch() DWWULEXWH ZRUNV WKH VDPH DV ZH GHVFULEHG LQ &KDSWHU ,W DOORZV \RX WR
VSHFLI\ ZKHWKHU \RX ZDQW WKH DVVRFLDWLRQ WR EH OD]LO\ RU HDJHUO\ ORDGHG ,Q &KDS
WHU ZH¦OO VKRZ \RX KRZ \RX FDQ HDJHUO\ IHWFK D UHODWLRQVKLS ZLWK -3$ 4/ RU WKH
&ULWHULD $3, HYHQ ZKHQ \RX KDYH PDUNHG WKH FetchType DV LAZY
7KH optional() DWWULEXWH VSHFLILHV ZKHWKHU WKLV UHODWLRQVKLS FDQ EH QXOO ,I WKLV LV VHW WR
false WKHQ D QRQ QXOO UHODWLRQVKLS PXVW H[LVW EHWZHHQ WKH WZR HQWLWLHV
7KH cascade() DWWULEXWH LV D ELW FRPSOLFDWHG :H¦OO GLVFXVV LW ODWHU LQ WKLV FKDSWHU DV DOO
UHODWLRQVKLS W\SHV KDYH WKLV DWWULEXWH
7KH mappedBy() DWWULEXWH LV IRU ELGLUHFWLRQDO UHODWLRQVKLSV DQG LV GLVFXVVHG LQ WKH QH[W
VHFWLRQ
7KH orphanRemoval() DWWULEXWH LV QHZ WR -3$ DQG GHILQHV ZKHWKHU UHPRYLQJ WKH
UHODWLRQVKLS VKRXOG DOVR UHVXOW LQ D UHPRYDO RI WKH UHIHUUHG HQWLW\

Primary-key join columns


6RPHWLPHV WKH SULPDU\ NH\V RI WKH WZR UHODWHG HQWLWLHV DUH XVHG LQVWHDG RI D VSHFLILF
MRLQ FROXPQ ,Q WKLV FDVH WKH SULPDU\ NH\V RI WKH UHODWHG HQWLWLHV DUH LGHQWLFDO DQG WKHUH
LV QR QHHG IRU D VSHFLILF MRLQ FROXPQ
,Q WKLV PDSSLQJ VFHQDULR \RX DUH UHTXLUHG WR XVH DQ DOWHUQDWLYH DQQRWDWLRQ WR GHVFULEH
WKH PDSSLQJ¢@javax.persistence.PrimaryKeyJoinColumn
public @interface PrimaryKeyJoinColumn
{
String name() default "";
String referencedColumnName() default "";
String columnDefinition() default "";
}

7KH name() DWWULEXWH UHIHUV WR WKH SULPDU\ NH\ FROXPQ QDPH RI WKH HQWLW\ WKH DQQRWDWLRQ
LV DSSOLHG WR 8QOHVV \RXU HQWLW\ KDV D FRPSRVLWH SULPDU\ NH\ \RX FDQ OHDYH WKLV EODQN
DQG WKH SHUVLVWHQFH SURYLGHU ZLOO ILJXUH LW RXW
7KH referencedColumnName() LV WKH FROXPQ WR MRLQ WR RQ WKH UHODWHG HQWLW\ ,I WKLV LV OHIW
EODQN LW LV DVVXPHG WKDW WKH UHODWHG HQWLW\¦V SULPDU\ NH\ ZLOO EH XVHG
7KH columnDefinition() LV XVHG ZKHQ WKH SHUVLVWHQFH SURYLGHU LV JHQHUDWLQJ VFKHPD
DQG LWV YDOXH ZLOO VSHFLI\ WKH 64/ W\SH RI WKH referencedColumnName()
,I WKH SULPDU\ NH\ MRLQ LQ TXHVWLRQ LV RI D FRPSRVLWH QDWXUH WKHQ WKH
@javax.persistence.PrimaryKeyJoinColumns DQQRWDWLRQ LV DYDLODEOH WR \RX
public @interface PrimaryKeyJoinColumns
{
PrimaryKeyJoinColumn[] value();
}

The Seven Relationship Types | 175


6R ZH FRXOG XVH WKLV DQQRWDWLRQ WR PDS WKH Employee Address HQWLWLHV¦ RQH WR RQH
UHODWLRQVKLS
@OneToOne(cascade={CascadeType.ALL})
@PrimaryKeyJoinColumn
private Address address;

6LQFH ZH¦UH MRLQLQJ RQ WKH SULPDU\ NH\V RI WKH Employee DQG Address HQWLWLHV DQG WKH\
DUH QRW FRPSRVLWH NH\V ZH FDQ VLPSO\ DQQRWDWH WKH DGGUHVV SURSHUW\ RI Employee ZLWK
WKH GHIDXOWHG @PrimaryKeyJoinColumn DQQRWDWLRQ

Default relationship mapping


,I \RXU SHUVLVWHQFH SURYLGHU VXSSRUWV DXWR VFKHPD JHQHUDWLRQ \RX GR QRW QHHG WR
VSHFLI\ PHWDGDWD VXFK DV @JoinColumn RU @PrimaryKeyJoinColumn $XWR VFKHPD JHQHU
DWLRQ LV JUHDW ZKHQ \RX DUH GRLQJ IDVW SURWRW\SHV
@OneToOne
private Address address;

:KHQ \RX GR QRW VSHFLI\ DQ\ GDWDEDVH PDSSLQJ IRU D XQLGLUHFWLRQDO RQH WR RQH
UHODWLRQVKLS WKH SHUVLVWHQFH SURYLGHU ZLOO JHQHUDWH WKH QHFHVVDU\ IRUHLJQ NH\ PDSSLQJV
IRU \RX ,Q RXU HPSOR\HH DGGUHVV UHODWLRQVKLS H[DPSOH WKH IROORZLQJ WDEOHV ZRXOG EH
JHQHUDWHG
CREATE TABLE "PUBLIC"."EMPLOYEE"
(
ID bigint PRIMARY KEY NOT NULL,
ADDRESS_ID bigint
)
;

ALTER TABLE "PUBLIC"."EMPLOYEE"


ADD CONSTRAINT FK4AFD4ACEE5310533
FOREIGN KEY (ADDRESS_ID)
REFERENCES "PUBLIC"."ADDRESS"(ADDRESS_ID)
;

)RU XQLGLUHFWLRQDO RQH WR RQH UHODWLRQVKLSV WKH GHIDXOW PDSSLQJ FUHDWHV D IRUHLJQ NH\
FROXPQ QDPHG IURP D FRPELQDWLRQ RI WKH SURSHUW\ \RX DUH PDSSLQJ IROORZHG E\
DQ _ XQGHUVFRUH FKDUDFWHU FRQFDWHQDWHG ZLWK WKH SULPDU\ NH\ FROXPQ QDPH RI WKH
UHIHUHQFHG WDEOH

One-to-One Bidirectional Relationship


:H FDQ H[SDQG RXU Employee HQWLW\ WR LQFOXGH D UHIHUHQFH WR D Computer HQWLW\ ZKLFK
PRGHOV WKH DVVRFLDWH¦V FRPSDQ\ SURYLGHG FRPSXWHU 7KH HPSOR\HH ZLOO PDLQWDLQ D
UHIHUHQFH WR KLV RU KHU FRPSXWHU DQG WKH FRPSXWHU ZLOO PDLQWDLQ D UHIHUHQFH EDFN WR
WKH HPSOR\HH 7KLV PDNHV JRRG VHQVH VLQFH ZH PD\ QHHG WR NQRZ WKH RZQHU RI D
FRPSXWHU

176 | Chapter 11:—Entity Relationships


Relational database schema
7KH Computer KDV D FRUUHVSRQGLQJ COMPUTER WDEOH ZKLFK ZLOO FRQWDLQ D SRLQWHU WR LWV
Employee RZQHU
CREATE TABLE "PUBLIC"."COMPUTER"
(
ID bigint PRIMARY KEY NOT NULL,
MAKE varchar,
MODEL varchar,
OWNER_ID bigint
)
;
ALTER TABLE "PUBLIC"."COMPUTER"
ADD CONSTRAINT FKE023E33B5EAFBFC
FOREIGN KEY (OWNER_ID)
REFERENCES "PUBLIC"."EMPLOYEE"(OWNER_ID)
;

2QH WR RQH ELGLUHFWLRQDO UHODWLRQVKLSV PD\ PRGHO UHODWLRQDO GDWDEDVH VFKHPDV LQ WKH
VDPH ZD\ DV RXU RQH WR RQH XQLGLUHFWLRQDO UHODWLRQVKLS LQ ZKLFK RQH RI WKH WDEOHV KROGV
D IRUHLJQ NH\ WKDW UHIHUHQFHV WKH RWKHU 5HPHPEHU WKDW LQ D UHODWLRQDO GDWDEDVH PRGHO
WKHUH LV QR VXFK QRWLRQ RI GLUHFWLRQDOLW\ VR WKH VDPH GDWDEDVH VFKHPD ZLOO EH XVHG IRU
ERWK XQLGLUHFWLRQDO DQG ELGLUHFWLRQDO REMHFW UHODWLRQVKLSV
7R PRGHO WKH UHODWLRQVKLS EHWZHHQ WKH Employee DQG Computer HQWLWLHV ZH QHHG WR GH
FODUH D UHODWLRQVKLS SURSHUW\ QDPHG owner LQ WKH Computer EHDQ FODVV
@Entity
public class Computer
{
...
@OneToOne
// Bidirectional relationship, mappedBy
// is declared on the non-owning side
private Employee owner;
...
}

6LPLODUO\ WKH Employee FODVV ZLOO KDYH D UHIHUHQFH WR WKH Computer


/**
* The employee's computer
*/
@OneToOne(mappedBy = "owner")
// Bidirectional relationship
private Computer computer;

7KH mappedBy() DWWULEXWH LV QHZ KHUH 7KLV DWWULEXWH VHWV XS WKH ELGLUHFWLRQDO UHODWLRQ
VKLS DQG WHOOV WKH SHUVLVWHQFH PDQDJHU WKDW WKH LQIRUPDWLRQ IRU PDSSLQJ WKLV UHODWLRQ
VKLS WR RXU WDEOHV LV VSHFLILHG LQ WKH Computer EHDQ FODVV VSHFLILFDOO\ WR WKH owner
SURSHUW\ RI Computer

The Seven Relationship Types | 177


+HUH LV DQ H[DPSOH IRU VHWWLQJ XS D ELGLUHFWLRQDO UHODWLRQVKLS
// Create a new Computer
final Computer computer = new Computer();
computer.setMake("Computicorp");
computer.setModel("ZoomFast 100");

// Create a new Employee


final Employee carloDeWolf = new Employee("Carlo de Wolf");

// Persist; now we have managed objects


EntityManager em = null; // Assume we have this
em.persist(carloDeWolf);
em.persist(computer);

// Associate *both* sides of a bidirectional relationship


carloDeWolf.setComputer(computer);
computer.setOwner(carloDeWolf);

:H KDYH WKH cascade() DWWULEXWH VHW WR HPSW\ VR ZH PXVW SHUIRUP WKH DVVRFLDWLRQ DIWHU
HDFK REMHFW LV SHUVLVWHG DQG WKHUHIRUH PDQDJHG :KHQ ZH GLVFXVV FDVFDGLQJ RSHUDWLRQV
\RX ZLOO VHH WKDW WKHUH DUH ZD\V WR SHUVLVW XQPDQDJHG REMHFWV DV SDUW RI DQ DVVRFLDWLRQ
DXWRPDWLFDOO\
7KHUH DUH VRPH SHFXOLDULWLHV ZLWK ELGLUHFWLRQDO UHODWLRQVKLSV :LWK DOO ELGLUHFWLRQDO
UHODWLRQVKLS W\SHV LQFOXGLQJ RQH WR RQH WKHUH LV DOZD\V WKH FRQFHSW RI DQ RZQLQJ VLGH
RI WKH UHODWLRQVKLS $OWKRXJK D setOwner() PHWKRG LV DYDLODEOH LQ WKH Computer EHDQ
FODVV LW ZLOO QRW FDXVH D FKDQJH LQ WKH SHUVLVWHQW UHODWLRQVKLS LI ZH VHW LW :KHQ ZH
PDUNHG WKH @OneToOne UHODWLRQVKLS LQ WKH Employee EHDQ FODVV ZLWK WKH mappedBy() DW
WULEXWH WKLV GHVLJQDWHG WKH Employee HQWLW\ DV WKH LQYHUVH VLGH RI WKH UHODWLRQVKLS 7KLV
PHDQV WKDW WKH Computer HQWLW\ LV WKH RZQLQJ VLGH RI WKH UHODWLRQVKLS

$OZD\V ZLUH ERWK VLGHV RI D ELGLUHFWLRQDO UHODWLRQVKLS ZKHQ PRGLI\LQJ


UHODWLRQVKLSV (QWLWLHV DUH OLNH DQ\ RWKHU -DYD REMHFW WKDW KDV DQ DVVRFL
DWLRQ WR DQRWKHU REMHFW <RX KDYH WR VHW WKH YDOXHV RI ERWK VLGHV RI WKH
UHODWLRQVKLS LQ PHPRU\ IRU WKH UHODWLRQVKLS WR EH XSGDWHG

,I WKH HPSOR\HH EURNH KLV FRPSXWHU \RX ZRXOG KDYH WR VHW WKH UHODWLRQVKLS WR QXOO RQ
ERWK VLGHV DQG WKHQ UHPRYH WKH Computer HQWLW\ IURP WKH GDWDEDVH

One-to-Many Unidirectional Relationship


(QWLW\ EHDQV FDQ DOVR PDLQWDLQ UHODWLRQVKLSV ZLWK PXOWLSOLFLW\ 7KLV PHDQV RQH HQWLW\
EHDQ FDQ DJJUHJDWH RU FRQWDLQ PDQ\ RWKHU HQWLW\ EHDQV )RU H[DPSOH DQ HPSOR\HH PD\
KDYH UHODWLRQVKLSV ZLWK PDQ\ SKRQHV HDFK RI ZKLFK UHSUHVHQWV D SKRQH QXPEHU 7KLV
LV YHU\ GLIIHUHQW IURP VLPSOH RQH WR RQH UHODWLRQVKLSV¢RU IRU WKDW PDWWHU IURP PXO
WLSOH RQH WR RQH UHODWLRQVKLSV ZLWK WKH VDPH W\SH RI EHDQ 2QH WR PDQ\ DQG PDQ\ WR
PDQ\ UHODWLRQVKLSV UHTXLUH WKH GHYHORSHU WR ZRUN ZLWK D FROOHFWLRQ RI UHIHUHQFHV LQVWHDG
RI D VLQJOH UHIHUHQFH ZKHQ DFFHVVLQJ WKH UHODWLRQVKLS ILHOG

178 | Chapter 11:—Entity Relationships


Relational database schema
7R LOOXVWUDWH D RQH WR PDQ\ XQLGLUHFWLRQDO UHODWLRQVKLS ZH ZLOO XVH D QHZ HQWLW\ EHDQ
WKH 3KRQH IRU ZKLFK ZH PXVW GHILQH D WDEOH WKH PHONE WDEOH
CREATE TABLE "PUBLIC"."PHONE"
(
ID bigint PRIMARY KEY NOT NULL,
NUMBER varchar,
TYPE varchar
)
;

7KLV LV PRGHOHG DV D VLPSOH Phone FODVV


@Entity
public class Phone
{
...
/**
* Phone number
*/
private String number;
...
}

2QH WR PDQ\ XQLGLUHFWLRQDO UHODWLRQVKLSV EHWZHHQ WKH EMPLOYEE DQG PHONE WDEOHV FRXOG
EH LPSOHPHQWHG LQ D YDULHW\ RI ZD\V )RU WKLV H[DPSOH ZH KDYH FKRVHQ WR LQWURGXFH D
QHZ WDEOH D MRLQ WDEOH WR PDS SKRQHV WR HPSOR\HHV
CREATE TABLE "PUBLIC"."EMPLOYEE_PHONE"
(
EMPLOYEE_ID bigint NOT NULL,
PHONES_ID bigint NOT NULL
)
;
ALTER TABLE "PUBLIC"."EMPLOYEE_PHONE"
ADD CONSTRAINT FK1E56289D581FE7C
FOREIGN KEY (PHONES_ID)
REFERENCES "PUBLIC"."PHONE"(PHONES_ID)
;
ALTER TABLE "PUBLIC"."EMPLOYEE_PHONE"
ADD CONSTRAINT FK1E56289DD9454221
FOREIGN KEY (EMPLOYEE_ID)
REFERENCES "PUBLIC"."EMPLOYEE"(EMPLOYEE_ID)
;

/LNHZLVH ZH FDQ LQWURGXFH D OLQN IURP Employee WR REWDLQ D FROOHFWLRQ RI PhoneV


/**
* All {@link Phone}s for this {@link Employee}
*/
@OneToMany
// Unidirectional relationship
private Collection<Phone> phones;

The Seven Relationship Types | 179


2XU GDWDEDVH VFKHPD LOOXVWUDWHV WKDW WKH VWUXFWXUH DQG UHODWLRQVKLSV RI WKH DFWXDO
GDWDEDVH FDQ GLIIHU IURP WKH UHODWLRQVKLSV DV GHILQHG LQ WKH SURJUDPPLQJ PRGHO ,Q WKLV
FDVH WKH UHODWLRQVKLS LQ WKH REMHFW PRGHO LV LQIHUUHG IURP WKH UHIHUHQFH Employee KDV WR
D Collection RI Phones EXW WKH GDWDEDVH FRQWDLQV D MRLQ WDEOH :KHQ \RX DUH GHDOLQJ
ZLWK OHJDF\ GDWDEDVHV L H GDWDEDVHV WKDW ZHUH HVWDEOLVKHG EHIRUH WKH (-% DSSOLFDWLRQ
LW¦V LPSRUWDQW WR KDYH WKH PDSSLQJ RSWLRQV -3$ DIIRUGV VR WKDW WKH REMHFW PRGHO LV QRW
GLFWDWHG E\ WKH VFKHPD

Programming model
<RX GHFODUH RQH WR PDQ\ UHODWLRQVKLSV XVLQJ WKH @javax.persistence.OneToMany
DQQRWDWLRQ
package javax.persistence;

@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OneToMany
{
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
boolean orphanRemoval() default false;
}

7KH DWWULEXWH GHILQLWLRQV DUH SUHWW\ PXFK WKH VDPH DV WKRVH IRU WKH @OneToOne
DQQRWDWLRQ
,Q WKH SURJUDPPLQJ PRGHO ZH UHSUHVHQW PXOWLSOLFLW\ E\ GHILQLQJ D UHODWLRQVKLS SURS
HUW\ WKDW FDQ SRLQW WR PDQ\ HQWLW\ EHDQV DQG DQQRWDWLQJ LW ZLWK @OneToMany 7R KROG
WKLV W\SH RI GDWD ZH¦OO HPSOR\ VRPH GDWD VWUXFWXUHV IURP WKH java.util SDFNDJH
Collection List Map DQG Set 7KH Collection PDLQWDLQV D KRPRJHQHRXV JURXS RI
HQWLW\ REMHFW UHIHUHQFHV ZKLFK PHDQV WKDW LW FRQWDLQV PDQ\ UHIHUHQFHV WR RQH NLQG RI
HQWLW\ EHDQ 7KH Collection W\SH PD\ FRQWDLQ GXSOLFDWH UHIHUHQFHV WR WKH VDPH HQWLW\
EHDQ DQG WKH Set W\SH PD\ QRW
7R LOOXVWUDWH KRZ DQ HQWLW\ EHDQ XVHV D FROOHFWLRQ EDVHG UHODWLRQVKLS OHW¦V ORRN DW VRPH
FRGH WKDW LQWHUDFWV ZLWK WKH EntityManager
// Create an Employee
final Employee jaikiranPai = new Employee("Jaikiran Pai");

// Create a couple Phones


final Phone phone1 = new Phone("800-USE-EJB3");
final Phone phone2 = new Phone("8675309");

// Persist
final EntityManager em = null; // Assume we have this
em.persist(jaikiranPai);
em.persist(phone1);
em.persist(phone2);

180 | Chapter 11:—Entity Relationships


// Associate
jaikiranPai.getPhones().add(phone1);
jaikiranPai.getPhones().add(phone2);

,I \RX QHHG WR UHPRYH D Phone IURP WKH UHODWLRQVKLS \RX QHHG WR UHPRYH WKH Phone IURP
ERWK WKH FROOHFWLRQ DQG WKH GDWDEDVH
jaikiranPai.getPhones().remove(phone1);
em.remove(phone1);

5HPRYLQJ WKH Phone IURP WKH Employee¦V FROOHFWLRQ GRHV QRW UHPRYH WKH Phone IURP WKH
GDWDEDVH <RX KDYH WR GHOHWH WKH Phone H[SOLFLWO\ RWKHUZLVH LW ZLOO EH RUSKDQHG 7KH
orphanRemoval DWWULEXWH RI @OneToMany PD\ UHPRYH WKH RUSKDQHG SKRQH DXWRPDWLFDOO\
LI VHW WR true

Many-to-One Unidirectional Relationship


0DQ\ WR RQH XQLGLUHFWLRQDO UHODWLRQVKLSV UHVXOW ZKHQ PDQ\ HQWLW\ EHDQV UHIHUHQFH D
VLQJOH HQWLW\ EHDQ EXW WKH UHIHUHQFHG HQWLW\ EHDQ LV XQDZDUH RI WKH UHODWLRQVKLS ,Q RXU
H[DPSOH FRPSDQ\ ZH KDYH D VHULHV RI CustomerV ZKR DUH HDFK DVVLJQHG WR DQ
Employee ZKR LV WKH SULPDU\ FRQWDFW IRU WKH FXVWRPHU DFFRXQW $Q Employee PD\ EH WKH
SRLQW SHUVRQ IRU PDQ\ CustomerV EXW WKH UHODWLRQVKLS ZLOO EH RQH ZD\ FXVWRPHUV ZLOO
NQRZ ZKR WKHLU SULPDU\ FRQWDFW LV EXW EmployeeV ZLOO QRW UHIHU WR DOO RI WKHLU CustomerV

Relational database schema


+HUH ZH LQWURGXFH D CUSTOMER WDEOH WR PRGHO RXU FXVWRPHUV
CREATE TABLE "PUBLIC"."CUSTOMER"
(
ID bigint PRIMARY KEY NOT NULL,
NAME varchar,
PRIMARYCONTACT_ID bigint
)
;
ALTER TABLE "PUBLIC"."CUSTOMER"
ADD CONSTRAINT FK27FBE3FE9BACAAF1
FOREIGN KEY (PRIMARYCONTACT_ID)
REFERENCES "PUBLIC"."EMPLOYEE"(PRIMARYCONTACT_ID)
;

Programming model
0DQ\ WR RQH UHODWLRQVKLSV DUH GHVFULEHG ZLWK WKH @javax.persistence.ManyToOne
DQQRWDWLRQ
public @interface ManyToOne
{
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;

The Seven Relationship Types | 181


boolean optional() default true;
}

7KH DWWULEXWH GHILQLWLRQV DUH SUHWW\ PXFK WKH VDPH DV WKRVH IRU WKH @OneToOne
DQQRWDWLRQ
7KH SURJUDPPLQJ PRGHO LV TXLWH VLPSOH IRU RXU UHODWLRQVKLS :H DGG D
primaryContact SURSHUW\ WR RXU Customer HQWLW\ EHDQ FODVV DQG DQQRWDWH LW ZLWK WKH
@ManyToOne DQQRWDWLRQ
@Entity
public class Customer
{
...
/**
* The primary {@link Employee} contact for this {@link Customer}
*/
@ManyToOne
// Unidirectional
private Employee primaryContact;
...
}

7KH UHODWLRQVKLS EHWZHHQ WKH Employee DQG Customer HQWLWLHV LV XQLGLUHFWLRQDO VR WKH
Employee EHDQ FODVV GRHVQ¦W GHILQH DQ\ UHODWLRQVKLS EDFN WR WKH Customer
$OO RI WKLV VKRXOG EH PXQGDQH WR \RX QRZ 7KH LPSDFW RI H[FKDQJLQJ Employee UHIHU
HQFHV EHWZHHQ Customer HQWLWLHV ZRUNV MXVW DV ZH¦YH VHHQ ZLWK WKH SUHYLRXV UHODWLRQVKLS
W\SHV

One-to-Many Bidirectional Relationship


2QH WR PDQ\ DQG PDQ\ WR RQH ELGLUHFWLRQDO UHODWLRQVKLSV VRXQG OLNH WKH\¦UH GLIIHUHQW
EXW WKH\¦UH QRW $ RQH WR PDQ\ ELGLUHFWLRQDO UHODWLRQVKLS RFFXUV ZKHQ RQH HQWLW\ EHDQ
PDLQWDLQV D FROOHFWLRQ EDVHG UHODWLRQVKLS SURSHUW\ ZLWK DQRWKHU HQWLW\ EHDQ DQG HDFK
HQWLW\ EHDQ UHIHUHQFHG LQ WKH FROOHFWLRQ PDLQWDLQV D VLQJOH UHIHUHQFH EDFN WR LWV DJJUH
JDWLQJ EHDQ )RU H[DPSOH LQ RXU FRPSDQ\ DQ HPSOR\HH KDV D PDQDJHU DQG OLNHZLVH D
PDQDJHU KDV PDQ\ GLUHFW UHSRUWV 7KH UHODWLRQVKLS LV D RQH WR PDQ\ ELGLUHFWLRQDO UH
ODWLRQVKLS IURP WKH SHUVSHFWLYH RI WKH PDQDJHU DQ Employee DQG D PDQ\ WR RQH
ELGLUHFWLRQDO UHODWLRQVKLS IURP WKH SHUVSHFWLYH RI WKH UHSRUW DOVR DQ Employee )RU
IXQ¦V VDNH OHW¦V ODEHO £UHSRUWV¤ LQ WKLV VHQVH DV £SHRQV ¤ 7KLV EHFRPHV DQ LQWHUHVWLQJ
H[HUFLVH DV ZHOO EHFDXVH LW VKRZV WKDW UHODWLRQVKLSV PD\ H[LVW ZLWKLQ D VLQJOH HQWLW\ W\SH

Relational database schema


)LUVW ZH QHHG WR HTXLS RXU EMPLOYEE WDEOH ZLWK WKH VXSSRUW QHFHVVDU\ WR PRGHO WKH
PDQDJHU SHRQ UHODWLRQVKLS
CREATE TABLE "PUBLIC"."EMPLOYEE"
(
ID bigint PRIMARY KEY NOT NULL,

182 | Chapter 11:—Entity Relationships


NAME varchar,
MANAGER_ID bigint
)
;
ALTER TABLE "PUBLIC"."EMPLOYEE"
ADD CONSTRAINT FK4AFD4ACE378204C2
FOREIGN KEY (MANAGER_ID)
REFERENCES "PUBLIC"."EMPLOYEE"(MANAGER_ID)
;

1RZ HDFK Employee KDV D UHIHUHQFH WR KLV RU KHU PDQDJHU

Programming model
%HFDXVH WKLV LV D ELGLUHFWLRQDO UHODWLRQVKLS WKH PDQDJHU NQRZV KLV RU KHU UHSRUWV DQG
DOVR KLV RU KHU RZQ PDQDJHU 7KH Employee FODVV PD\ WKHUHIRUH FRQWDLQ
/**
* Manager of the {@link Employee}
*/
@ManyToOne
private Employee manager;

/**
* {@link Employee}s reporting to this {@link Employee}
*/
@OneToMany(mappedBy = "manager")
private Collection<Employee> peons;

7KH HQWLUH UHODWLRQVKLS KHUH LV FRQWDLQHG ZLWKLQ WKH Employee FODVV $V ZLWK DOO
ELGLUHFWLRQDO UHODWLRQVKLSV WKH LQYHUVH VLGH VSHFLILHV mappedBy WR LQGLFDWH WKH SURSHUW\
WR DFW DV WKH RZQLQJ VLGH
-DYD 3HUVLVWHQFH FXUUHQWO\ UHTXLUHV WKDW WKH PDQ\ WR RQH VLGH DOZD\V EH WKH RZQHU 7KLV
PD\ VHHP YHU\ FRQIXVLQJ EXW LI \RX REH\ WKH FDUGLQDO UXOH RI DOZD\V ZLULQJ ERWK VLGHV
RI D UHODWLRQVKLS WKHQ \RX ZLOO KDYH QR SUREOHPV

$OZD\V ZLUH ERWK VLGHV RI D ELGLUHFWLRQDO UHODWLRQVKLS LQ \RXU -DYD FRGH

Usage
&OLHQW XVDJH LV DV ZH¦YH VHHQ EHIRUH
// Create a few Employees
final Employee alrubinger = new Employee("Andrew Lee Rubinger");
final Employee carloDeWolf = new Employee("Carlo de Wolf - SuperLead!");
final Employee jaikiranPai = new Employee("Jaikiran Pai");
final Employee bigD = new Employee("Big D");

// Persist
em.persist(jaikiranPai);

The Seven Relationship Types | 183


em.persist(alrubinger);
em.persist(carloDeWolf);
em.persist(bigD);

// Associate *both* sides of the bidirectional relationship


final Collection<Employee> peonsOfD = bigD.getPeons();
peonsOfD.add(alrubinger);
peonsOfD.add(carloDeWolf);
peonsOfD.add(jaikiranPai);
alrubinger.setManager(bigD);
carloDeWolf.setManager(bigD);
jaikiranPai.setManager(bigD);

Many-to-Many Bidirectional Relationship


0DQ\ WR PDQ\ ELGLUHFWLRQDO UHODWLRQVKLSV RFFXU ZKHQ PDQ\ EHDQV PDLQWDLQ D
FROOHFWLRQ EDVHG UHODWLRQVKLS SURSHUW\ ZLWK DQRWKHU EHDQ DQG HDFK EHDQ UHIHUHQFHG LQ
WKH FROOHFWLRQ PDLQWDLQV D FROOHFWLRQ EDVHG UHODWLRQVKLS SURSHUW\ EDFN WR WKH DJJUHJDW
LQJ EHDQV )RU H[DPSOH LQ RXU H[DPSOH FRPSDQ\ HYHU\ Employee PD\ EHORQJ WR PDQ\
TeamV DQG HDFK Team PD\ EH FRPSRVHG RI PDQ\ Employees

Relational database schema


7KH EMPLOYEE DQG TEAM WDEOHV PD\ EH IDLUO\ VLPSOH DQG QHLWKHU ZLOO KDYH D GLUHFW UHIHU
HQFH WR WKH RWKHU
CREATE TABLE "PUBLIC"."TEAM"
(
ID bigint PRIMARY KEY NOT NULL,
NAME varchar
)
;
CREATE TABLE "PUBLIC"."EMPLOYEE"
(
ID bigint PRIMARY KEY NOT NULL,
NAME varchar
)
;

$JDLQ ZH XVH D MRLQ WDEOH WR HVWDEOLVK D PDQ\ WR PDQ\ ELGLUHFWLRQDO UHODWLRQVKLS DQG
ZH¦OO FDOO WKLV WKH TEAM_EMPLOYEE WDEOH +HUH ZH PDLQWDLQ WZR IRUHLJQ NH\ FROXPQV¢
RQH IRU WKH EMPLOYEE WDEOH DQG DQRWKHU IRU WKH TEAM WDEOH
CREATE TABLE "PUBLIC"."TEAM_EMPLOYEE"
(
TEAMS_ID bigint NOT NULL,
MEMBERS_ID bigint NOT NULL
)
;
ALTER TABLE "PUBLIC"."TEAM_EMPLOYEE"
ADD CONSTRAINT FKA63C2502B25E948
FOREIGN KEY (TEAMS_ID)
REFERENCES "PUBLIC"."TEAM"(TEAMS_ID)

184 | Chapter 11:—Entity Relationships


;
ALTER TABLE "PUBLIC"."TEAM_EMPLOYEE"
ADD CONSTRAINT FKA63C25052E6C3D6
FOREIGN KEY (MEMBERS_ID)
REFERENCES "PUBLIC"."EMPLOYEE"(MEMBERS_ID)

Programming model
0DQ\ WR PDQ\ UHODWLRQVKLSV DUH ORJLFDOO\ GHILQHG XVLQJ WKH @javax.persistence.Many
ToMany DQQRWDWLRQ
public @interface ManyToMany
{
Class targetEntity( ) default void.class;
CascadeType[] cascade( ) default {};
FetchType fetch( ) default LAZY;
String mappedBy( ) default "";
}

7R PRGHO WKH PDQ\ WR PDQ\ ELGLUHFWLRQDO UHODWLRQVKLS EHWZHHQ WKH Employee DQG
Team HQWLWLHV ZH QHHG WR LQFOXGH FROOHFWLRQ EDVHG UHODWLRQVKLS SURSHUWLHV LQ ERWK EHDQ
FODVVHV
@Entity
public class Employee
{
...
/**
* The {@link Team}s to which this {@link Employee} belongs
*/
@ManyToMany(mappedBy = "members")
private Collection<Team> teams;
...
}

@Entity
public class Team
{
...
/**
* {@link Employee}s on this {@link Task}.
*/
@ManyToMany
private Collection<Employee> members;
...
}

7KH UHODWLRQVKLS LV GHFODUHG DV D java.util.Collection :H FRXOG DOVR XVH D Set W\SH


ZKLFK ZRXOG FRQWDLQ RQO\ XQLTXH TeamV DQG QR GXSOLFDWHV 7KH HIIHFWLYHQHVV RI WKH
Set FROOHFWLRQ W\SH GHSHQGV ODUJHO\ RQ UHIHUHQWLDO LQWHJULW\ FRQVWUDLQWV HVWDEOLVKHG LQ
WKH XQGHUO\LQJ GDWDEDVH
$V ZLWK DOO ELGLUHFWLRQDO UHODWLRQVKLSV WKHUH KDV WR EH DQ RZQLQJ VLGH ,Q WKLV FDVH LW LV
WKH Team HQWLW\ 6LQFH WKH Team RZQV WKH UHODWLRQVKLS LWV EHDQ FODVV PD\ KDYH WKH

The Seven Relationship Types | 185


@JoinTable PDSSLQJ WKRXJK LQ RXU H[DPSOH ZH FDQ DFFHSW WKH GHIDXOWV 7KH
joinColumns() DWWULEXWH FRXOG LGHQWLI\ WKH IRUHLJQ NH\ FROXPQ LQ WKH TEAM_EMPLOYEE
WDEOH WKDW UHIHUHQFHV WKH TEAM WDEOH ZKHUHDV WKH inverseJoinColumns() DWWULEXWH FRXOG
LGHQWLI\ WKH IRUHLJQ NH\ WKDW UHIHUHQFHV WKH EMPLOYEE WDEOH
/LNH ZLWK @OneToMany UHODWLRQVKLSV LI \RX DUH XVLQJ \RXU SHUVLVWHQFH SURYLGHU¦V DXWR
VFKHPD JHQHUDWLRQ IDFLOLWLHV \RX GR QRW QHHG WR VSHFLI\ D @JoinTable PDSSLQJ 7KH
-DYD 3HUVLVWHQFH VSHFLILFDWLRQ KDV D GHIDXOW PDSSLQJ IRU @ManyToMany UHODWLRQVKLSV DQG
ZLOO FUHDWH WKH MRLQ WDEOH IRU \RX
$V ZLWK RQH WR PDQ\ ELGLUHFWLRQDO UHODWLRQVKLSV WKH mappedBy() DWWULEXWH LGHQWLILHV WKH
SURSHUW\ RQ WKH Team EHDQ FODVV WKDW GHILQHV WKH UHODWLRQVKLS 7KLV DOVR LGHQWLILHV WKH
Employee HQWLW\ DV WKH LQYHUVH VLGH RI WKH UHODWLRQVKLS
$V IDU DV PRGLI\LQJ DQG LQWHUDFWLQJ ZLWK WKH UHODWLRQVKLS SURSHUWLHV WKH VDPH RZQHU
VKLS UXOHV DSSO\ DV ZH VDZ LQ WKH RQH WR PDQ\ ELGLUHFWLRQDO H[DPSOH
// Create a few employees
final Employee pmuir = new Employee("Pete Muir");
final Employee dallen = new Employee("Dan Allen");
final Employee aslak = new Employee("Aslak Knutsen");

// Create some teams


final Team seam = new Team("Seam");
final Team arquillian = new Team("Arquillian");

// Get EM
final EntityManager em = null; // Assume we have this

// Persist
em.persist(pmuir);
em.persist(dallen);
em.persist(aslak);
em.persist(seam);
em.persist(arquillian);

// Associate *both* directions


seam.getMembers().add(dallen);
seam.getMembers().add(pmuir);
seam.getMembers().add(aslak);
arquillian.getMembers().add(dallen);
arquillian.getMembers().add(pmuir);
arquillian.getMembers().add(aslak);
aslak.getTeams().add(seam);
aslak.getTeams().add(arquillian);
dallen.getTeams().add(seam);
dallen.getTeams().add(arquillian);
pmuir.getTeams().add(seam);
pmuir.getTeams().add(arquillian);

186 | Chapter 11:—Entity Relationships


Many-to-Many Unidirectional Relationship
0DQ\ WR PDQ\ XQLGLUHFWLRQDO UHODWLRQVKLSV RFFXU ZKHQ PDQ\ EHDQV PDLQWDLQ D
FROOHFWLRQ EDVHG UHODWLRQVKLS ZLWK DQRWKHU EHDQ EXW WKH EHDQ UHIHUHQFHG LQ WKH
Collection GRHV QRW PDLQWDLQ D FROOHFWLRQ EDVHG UHODWLRQVKLS EDFN WR WKH DJJUHJDWLQJ
EHDQV ,Q RXU H[DPSOH ZH PD\ DVVLJQ DQ\ QXPEHU RI TaskV WR DQ\ QXPEHU RI
EmployeeV DQG EmployeeV PD\ EH DVVLJQHG WR DQ\ QXPEHU RI TaskV :H¦OO PDLQWDLQ D
UHIHUHQFH IURP Task WR Employee EXW QRW WKH RWKHU ZD\ DURXQG

Relational database schema


2XU ILUVW RUGHU RI EXVLQHVV LV WR GHFODUH D TASK WDEOH
CREATE TABLE "PUBLIC"."TASK"
(
ID bigint PRIMARY KEY NOT NULL,
DESCRIPTION varchar
)
;

$JDLQ ZH¦OO PDNH D MRLQ WDEOH WR PDS TaskV WR EmployeeV


CREATE TABLE "PUBLIC"."TASK_EMPLOYEE"
(
TASK_ID bigint NOT NULL,
OWNERS_ID bigint NOT NULL
)
;
ALTER TABLE "PUBLIC"."TASK_EMPLOYEE"
ADD CONSTRAINT FK7B1EDC2832EBEA41
FOREIGN KEY (TASK_ID)
REFERENCES "PUBLIC"."TASK"(TASK_ID)
;
ALTER TABLE "PUBLIC"."TASK_EMPLOYEE"
ADD CONSTRAINT FK7B1EDC28A3E4776F
FOREIGN KEY (OWNERS_ID)
REFERENCES "PUBLIC"."EMPLOYEE"(OWNERS_ID)
;

7KLV PDQ\ WR PDQ\ XQLGLUHFWLRQDO UHODWLRQVKLS ORRNV D ORW OLNH WKH MRLQ WDEOH PDSSLQJ
IRU WKH PDQ\ WR PDQ\ ELGLUHFWLRQDO UHODWLRQVKLS GLVFXVVHG HDUOLHU 7KH ELJ GLIIHUHQFH LV
WKDW WKH REMHFW PRGHO ZLOO PDLQWDLQ D UHIHUHQFH RQO\ LQ RQH GLUHFWLRQ

Programming model
7R PRGHO WKLV UHODWLRQVKLS ZH QHHG WR DGG D FROOHFWLRQ EDVHG UHODWLRQVKLS ILHOG IRU
Employee EHDQV WR WKH Task
@Entity
public class Task
{
...
/**
* {@link Employee} in charge of this {@link Task}

The Seven Relationship Types | 187


*/
@ManyToMany
private Collection<Employee> owners;
...
}

%HFDXVH WKH UHODWLRQVKLS LV XQLGLUHFWLRQDO WKHUH DUH QR RZQLQJ RU LQYHUVH VLGHV DQG ZH
PD\ RPLW WKH mappedBy DWWULEXWH RI @ManyToMany
8VDJH LV VLPLODU WR ZKDW ZH¦YH DOUHDG\ VHHQ
// Create a couple of employees
final Employee smarlow = new Employee("Scott Marlow");
final Employee jpederse = new Employee("Jesper Pedersen");

// Create a couple of tasks


final Task task1 = new Task("Go to the Java User's Group in Boston");
final Task task2 = new Task("Help Shelly McGowan with testsuite setup");

// Persist
final EntityManager em = null; // Assume we have this
em.persist(smarlow);
em.persist(jpederse);
em.persist(task1);
em.persist(task2);

// Associate
task1.getOwners().add(smarlow);
task1.getOwners().add(jpederse);
task2.getOwners().add(smarlow);
task2.getOwners().add(jpederse);

Mapping Collection-Based Relationships


7KH RQH WR PDQ\ DQG PDQ\ WR PDQ\ H[DPSOHV ZH¦YH VHHQ VR IDU KDYH XVHG WKH
java.util.Collection DQG java.util.Set W\SHV 7KH -DYD 3HUVLVWHQFH VSHFLILFDWLRQ DOVR
DOORZV \RX WR UHSUHVHQW D UHODWLRQVKLS ZLWK D java.util.List RU D java.util.Map

Ordered List-Based Relationship


7KH java.util.List LQWHUIDFH FDQ H[SUHVV FROOHFWLRQ EDVHG UHODWLRQVKLSV <RX GR QRW
QHHG DQ\ VSHFLDO PHWDGDWD LI \RX ZDQW WR XVH D List UDWKHU WKDQ D Set RU Collection
W\SH ,Q WKLV FDVH WKH List DFWXDOO\ JLYHV \RX D EDJ VHPDQWLF DQ XQRUGHUHG FROOHFWLRQ
WKDW DOORZV GXSOLFDWHV $ List W\SH FDQ JLYH \RX WKH DGGLWLRQDO DELOLW\ WR RUGHU WKH
UHWXUQHG UHODWLRQVKLS EDVHG RQ D VSHFLILF VHW RI FULWHULD 7KLV UHTXLUHV WKH DGGLWLRQDO
PHWDGDWD SURYLGHG E\ WKH @javax.persistence.OrderBy DQQRWDWLRQ
package javax.persistence;

@Target({METHOD, FIELD}) @Retention(RUNTIME)


public @interface OrderBy
{

188 | Chapter 11:—Entity Relationships


String value( ) default "";
}

7KH value() DWWULEXWH DOORZV \RX WR GHFODUH SDUWLDO -3$ 4/ WKDW VSHFLILHV KRZ \RX ZDQW
WKH UHODWLRQVKLS WR EH RUGHUHG ZKHQ LW LV IHWFKHG IURP WKH GDWDEDVH ,I WKH value()
DWWULEXWH LV OHIW HPSW\ WKH List LV VRUWHG LQ DVFHQGLQJ RUGHU EDVHG RQ WKH YDOXH RI WKH
SULPDU\ NH\
/HW¦V WDNH WKH Employee Team UHODWLRQVKLS ZKLFK LV D PDQ\ WR PDQ\ ELGLUHFWLRQDO UHOD
WLRQVKLS DQG KDYH WKH teams DWWULEXWH RI Employee UHWXUQ D List WKDW LV VRUWHG
DOSKDEHWLFDOO\ E\ WKH Team HQWLW\¦V QDPH
@Entity
public class Employee
{
...
@ManyToMany
@OrderBy("name ASC")
private List<Team> teams;
...
}

"name ASC" WHOOV WKH SHUVLVWHQFH SURYLGHU WR VRUW WKH Team¦V name LQ DVFHQGLQJ RUGHU <RX
FDQ XVH ASC IRU DVFHQGLQJ RUGHU DQG DESC IRU GHVFHQGLQJ RUGHU <RX FDQ DOVR VSHFLI\
DGGLWLRQDO UHVWULFWLRQV VXFK DV @OrderBy('name asc, otherattribute asc") ,Q WKLV
FDVH WKH OLVW ZLOO EH RUGHUHG E\ lastname DQG IRU GXSOLFDWH QDPHV LW ZLOO EH RUGHUHG
E\ WKH otherattribute

Map-Based Relationship
7KH java.util.Map LQWHUIDFH FDQ EH XVHG WR H[SUHVV FROOHFWLRQ EDVHG UHODWLRQVKLSV ,Q
WKLV FDVH WKH SHUVLVWHQFH SURYLGHU FUHDWHV D PDS ZLWK WKH NH\ EHLQJ D VSHFLILF SURSHUW\
RI WKH UHODWHG HQWLW\ DQG WKH YDOXH EHLQJ WKH HQWLW\ LWVHOI ,I \RX XVH D java.util.Map \RX
PXVW XVH WKH @javax.persistence.MapKey DQQRWDWLRQ
package javax.persistence;

@Target({METHOD, FIELD}) @Retention(RUNTIME)


public @interface MapKey
{
String name( ) default "";
}

7KH name() DWWULEXWH LV WKH QDPH RI WKH SHUVLVWHQW SURSHUW\ WKDW \RX ZDQW WR UHSUHVHQW
WKH NH\ ILHOG RI WKH PDS REMHFW ,I \RX OHDYH WKLV EODQN LW LV DVVXPHG \RX DUH XVLQJ WKH
SULPDU\ NH\ RI WKH UHODWHG HQWLW\ DV WKH NH\ RI WKH PDS
)RU DQ H[DPSOH OHW¦V XVH D PDS WR UHSUHVHQW WKH RQH WR PDQ\ XQLGLUHFWLRQDO Employee
Phone UHODWLRQVKLS GLVFXVVHG HDUOLHU LQ WKLV FKDSWHU
@Entity
public class Employee

Mapping Collection-Based Relationships | 189


{
...
@OneToMany
@MapKey(name="number")
private Map<String,Phone> phones;
...
}

,Q WKLV H[DPSOH WKH phones SURSHUW\ RI Employee ZLOO UHWXUQ D java.util.Map ZKHUH WKH
NH\ LV WKH number SURSHUW\ RI WKH Phone HQWLW\ DQG WKH YDOXH LV RI FRXUVH WKH Phone HQWLW\
LWVHOI 7KHUH LV QR H[WUD FROXPQ WR NHHS WKH PDS NH\ VLQFH WKH PDS NH\ LV ERUURZHG
IURP WKH Phone HQWLW\

Detached Entities and FetchType


,Q &KDSWHU ZH GLVFXVVHG KRZ PDQDJHG HQWLW\ LQVWDQFHV EHFRPH GHWDFKHG IURP D
SHUVLVWHQFH FRQWH[W ZKHQ WKH SHUVLVWHQFH FRQWH[W HQGV 6LQFH WKHVH HQWLW\ LQVWDQFHV DUH
QR ORQJHU PDQDJHG E\ DQ\ SHUVLVWHQFH FRQWH[W WKH\ PD\ KDYH XQLQLWLDOL]HG SURSHUWLHV
RU UHODWLRQVKLSV ,I \RX DUH UHWXUQLQJ WKHVH GHWDFKHG HQWLWLHV WR \RXU FOLHQWV DQG EDVLFDOO\
XVLQJ WKHP DV GDWD WUDQVIHU REMHFWV EHWZHHQ WKH FOLHQW DQG VHUYHU \RX QHHG WR IXOO\
XQGHUVWDQG WKH HIIHFWV RI DFFHVVLQJ DQ\ XQLQLWLDOL]HG UHODWLRQVKLSV
:KHQ DQ HQWLW\ LQVWDQFH EHFRPHV GHWDFKHG LWV VWDWH PLJKW QRW EH IXOO\ LQLWLDOL]HG
EHFDXVH VRPH RI LWV SHUVLVWHQW SURSHUWLHV RU UHODWLRQVKLSV PD\ EH PDUNHG DV OD]LO\ ORDGHG
LQ WKH PDSSLQJ PHWDGDWD (DFK UHODWLRQVKLS DQQRWDWLRQ KDV D fetch() DWWULEXWH WKDW
VSHFLILHV ZKHWKHU WKH UHODWLRQVKLS SURSHUW\ LV ORDGHG ZKHQ WKH HQWLW\ LV TXHULHG ,I WKH
fetch() DWWULEXWH LV VHW WR FetchType.LAZY WKHQ WKH UHODWLRQVKLS LV QRW LQLWLDOL]HG XQWLO
LW LV WUDYHUVHG LQ \RXU FRGH
Employee employee = entityManager.find(Employee.class, id);
employee.getPhones().size();

,QYRNLQJ WKH size() PHWKRG RI WKH phones FROOHFWLRQ FDXVHV WKH UHODWLRQVKLS WR EH ORDGHG
IURP WKH GDWDEDVH ,W LV LPSRUWDQW WR QRWH WKDW WKLV OD]\ LQLWLDOL]DWLRQ GRHV QRW KDSSHQ
XQOHVV WKH HQWLW\ EHDQ LV EHLQJ PDQDJHG E\ D SHUVLVWHQFH FRQWH[W ,I WKH HQWLW\ EHDQ LV
GHWDFKHG WKH VSHFLILFDWLRQ LV QRW FOHDU RQ ZKDW DFWLRQV WKH SHUVLVWHQFH SURYLGHU VKRXOG
SHUIRUP ZKHQ DFFHVVLQJ DQ XQORDGHG UHODWLRQVKLS RI D GHWDFKHG HQWLW\ 0RVW SHUVLV
WHQFH SURYLGHUV WKURZ VRPH NLQG RI OD]\ LQVWDQWLDWLRQ H[FHSWLRQ ZKHQ \RX FDOO WKH
DFFHVVRU RI WKH UHODWLRQVKLS RU ZKHQ \RX WU\ WR LQYRNH DQ RSHUDWLRQ RQ WKH UHODWLRQVKLS
RI D GHWDFKHG HQWLW\
Employee employee = entityManager.find(Employee.class, id);
entityManager.detach(employee);
try
{
int numPhones = employee.getPhones().size();
}
catch (SomeVendorLazyInitializationException ex)
{
}

190 | Chapter 11:—Entity Relationships


,Q WKLV FRGH WKH DSSOLFDWLRQ KDV UHFHLYHG DQ LQVWDQFH RI D GHWDFKHG Employee HQWLW\ DQG
DWWHPSWV WR DFFHVV WKH phones UHODWLRQVKLS ,I WKH fetch() DWWULEXWH RI WKLV UHODWLRQVKLS
LV LAZY PRVW YHQGRU LPSOHPHQWDWLRQV ZLOO WKURZ D YHQGRU VSHFLILF H[FHSWLRQ 7KLV OD]\
LQLWLDOL]DWLRQ SUREOHP FDQ EH RYHUFRPH LQ WZR ZD\V 7KH REYLRXV ZD\ LV MXVW WR QDYLJDWH
WKH QHHGHG UHODWLRQVKLSV ZKLOH WKH HQWLW\ LQVWDQFH LV VWLOO PDQDJHG E\ D SHUVLVWHQFH
FRQWH[W 7KH VHFRQG ZD\ LV WR SHUIRUP WKH IHWFK HDJHUO\ ZKHQ \RX TXHU\ WKH HQWLW\ ,Q
&KDSWHU \RX ZLOO VHH WKDW WKH -3$ 4/ TXHU\ ODQJXDJH KDV D FETCH JOIN RSHUDWLRQ
WKDW DOORZV \RX WR SUHLQLWLDOL]H VHOHFWHG UHODWLRQVKLSV ZKHQ \RX LQYRNH D TXHU\
+RZ LV WKH SHUVLVWHQFH SURYLGHU DEOH WR WKURZ DQ H[FHSWLRQ ZKHQ DFFHVVLQJ WKH UHOD
WLRQVKLS ZKHQ WKH Employee FODVV LV D SODLQ -DYD FODVV" $OWKRXJK QRW GHILQHG LQ WKH
VSHFLILFDWLRQ WKH YHQGRU KDV D IHZ ZD\V WR LPSOHPHQW WKLV 2QH LV WKURXJK E\WHFRGH
PDQLSXODWLRQ RI WKH Employee FODVV ,Q -DYD (( WKH DSSOLFDWLRQ VHUYHU LV UHTXLUHG WR
SURYLGH KRRNV IRU E\WHFRGH PDQLSXODWLRQ IRU SHUVLVWHQFH SURYLGHUV ,Q -DYD 6( WKH
SHUVLVWHQFH SURYLGHU PD\ UHTXLUH DQ DGGLWLRQDO SRVW FRPSLODWLRQ VWHS RQ \RXU FRGH
EDVH $QRWKHU ZD\ IRU YHQGRUV WR LPSOHPHQW WKLV LV WR FUHDWH D SUR[\ FODVV WKDW LQKHULWV
IURP Employee DQG WKDW UHLPSOHPHQWV DOO WKH DFFHVVRU PHWKRGV WR DGG OD]\ LQLWLDOL]DWLRQ
FKHFNLQJ )RU FROOHFWLRQ EDVHG UHODWLRQVKLSV WKH SHUVLVWHQFH SURYLGHU FDQ MXVW SURYLGH
LWV RZQ LPSOHPHQWDWLRQ RI WKH FROOHFWLRQ DQG GR WKH OD]\ FKHFN WKHUH :KDWHYHU WKH
LPSOHPHQWDWLRQ PDNH D QRWH WR GLVFRYHU ZKDW \RXU SHUVLVWHQFH SURYLGHU ZLOO GR LQ WKH
GHWDFKHG OD]\ LQLWLDOL]DWLRQ VFHQDULR VR WKDW \RXU FRGH FDQ WDNH DSSURSULDWH PHDVXUHV
WR KDQGOH WKLV H[FHSWLRQ

Cascading
7KHUH LV RQH DQQRWDWLRQ DWWULEXWH WKDW ZH KDYH LJQRUHG VR IDU WKH cascade() DWWULEXWH
RI WKH @OneToOne @OneToMany @ManyToOne DQG @ManyToMany UHODWLRQVKLS DQQRWDWLRQV
7KLV VHFWLRQ GLVFXVVHV LQ GHWDLO WKH EHKDYLRU WKDW LV DSSOLHG ZKHQ XVLQJ WKH cascade()
DWWULEXWH
:KHQ \RX SHUIRUP DQ HQWLW\ PDQDJHU RSHUDWLRQ RQ DQ HQWLW\ EHDQ LQVWDQFH \RX FDQ
DXWRPDWLFDOO\ KDYH WKH VDPH RSHUDWLRQ SHUIRUPHG RQ DQ\ UHODWLRQVKLS SURSHUWLHV WKH
HQWLW\ PD\ KDYH 7KLV LV FDOOHG FDVFDGLQJ )RU H[DPSOH LI \RX DUH SHUVLVWLQJ D QHZ
Employee HQWLW\ ZLWK D QHZ DGGUHVV DQG SKRQH QXPEHU DOO \RX KDYH WR GR LV ZLUH WKH
REMHFW DQG WKH HQWLW\ PDQDJHU FDQ DXWRPDWLFDOO\ FUHDWH WKH HPSOR\HH DQG LWV UHODWHG
HQWLWLHV DOO LQ RQH persist() PHWKRG FDOO
Employee employee = new Employee();
customer.setAddress(new Address());
customer.getPhoneNumbers().add(new Phone());

// create them all in one entity manager invocation


entityManager.persist(employee);

:LWK WKH -DYD 3HUVLVWHQFH VSHFLILFDWLRQ FDVFDGLQJ FDQ EH DSSOLHG WR D YDULHW\ RI HQWLW\
PDQDJHU RSHUDWLRQV LQFOXGLQJ persist() merge() remove() DQG refresh() 7KLV

Cascading | 191
IHDWXUH LV HQDEOHG E\ VHWWLQJ WKH javax.persistence.CascadeType RI WKH UHODWLRQVKLS
DQQRWDWLRQ¦V cascade() DWWULEXWH 7KH CascadeType LV GHILQHG DV D -DYD HQXPHUDWLRQ
public enum CascadeType
{
ALL, PERSIST,
MERGE, REMOVE,
REFRESH
}

7KH ALL YDOXH UHSUHVHQWV DOO RI WKH FDVFDGH RSHUDWLRQV 7KH UHPDLQLQJ YDOXHV UHSUHVHQW
LQGLYLGXDO FDVFDGH RSHUDWLRQV 7KH cascade() DWWULEXWH LV DQ DUUD\ RI WKH FDVFDGH RSHU
DWLRQV \RX ZDQW DSSOLHG WR \RXU UHODWHG HQWLWLHV

PERSIST
PERSIST KDV WR GHDO ZLWK WKH FUHDWLRQ RI HQWLWLHV ZLWKLQ WKH GDWDEDVH ,I ZH KDG D
CascadeType RI PERSIST RQ WKH Employee VLGH RI RXU RQH WR RQH UHODWLRQVKLS \RX ZRXOG
QRW KDYH WR SHUVLVW \RXU FUHDWHG Address DV ZHOO ,W ZRXOG EH FUHDWHG IRU \RX 7KH SHU
VLVWHQFH SURYLGHU DOVR ZLOO H[HFXWH WKH DSSURSULDWH 64/ INSERT VWDWHPHQWV LQ WKH DS
SURSULDWH RUGHU IRU \RX
,I \RX GLG QRW KDYH D FDVFDGH SROLF\ RI PERSIST WKHQ \RX ZRXOG KDYH WR FDOO
EntityManager.persist() RQ WKH DGGUHVV REMHFW DV ZHOO DV ZH GR LQ WKH H[DPSOH

MERGE
MERGE GHDOV ZLWK HQWLW\ V\QFKURQL]DWLRQ PHDQLQJ LQVHUWV DQG PRUH LPSRUWDQWO\ XS
GDWHV 7KHVH DUHQ¦W XSGDWHV LQ WKH WUDGLWLRQDO VHQVH ,I \RX UHPHPEHU IURP SUHYLRXV
FKDSWHUV ZH PHQWLRQHG WKDW REMHFWV FRXOG EH GHWDFKHG IURP SHUVLVWHQW PDQDJHPHQW
DQG VHULDOL]HG WR D UHPRWH FOLHQW XSGDWHV FRXOG EH SHUIRUPHG ORFDOO\ RQ WKDW UHPRWH
FOLHQW WKH REMHFW LQVWDQFH ZRXOG EH VHQW EDFN WR WKH VHUYHU DQG WKH FKDQJHV ZRXOG EH
PHUJHG EDFN LQWR WKH GDWDEDVH 0HUJLQJ LV DERXW V\QFKURQL]LQJ WKH VWDWH RI D GHWDFKHG
REMHFW LQVWDQFH EDFN WR SHUVLVWHQW VWRUDJH
6R EDFN WR ZKDW MERGE PHDQV MERGE LV VLPLODU WR PERSIST ,I \RX KDYH D FDVFDGH SROLF\
RI MERGE WKHQ \RX GR QRW KDYH WR FDOO EntityManager.merge() IRU WKH FRQWDLQHG UHODWHG
HQWLW\
employee.setName("William");
employee.getAddress().setCity("Boston");
entityManager.merge(employee);

,Q WKLV H[DPSOH ZKHQ WKH employee YDULDEOH LV PHUJHG E\ WKH HQWLW\ PDQDJHU WKH HQWLW\
PDQDJHU ZLOO FDVFDGH WKH PHUJH WR WKH FRQWDLQHG address SURSHUW\ DQG WKH city DOVR
ZLOO EH XSGDWHG LQ WKH GDWDEDVH

192 | Chapter 11:—Entity Relationships


$QRWKHU LQWHUHVWLQJ WKLQJ DERXW MERGE LV WKDW LI \RX KDYH DGGHG DQ\ QHZ HQWLWLHV WR D
UHODWLRQVKLS WKDW KDYH QRW EHHQ FUHDWHG LQ WKH GDWDEDVH WKH\ ZLOO EH SHUVLVWHG DQG FUH
DWHG ZKHQ WKH merge() KDSSHQV
Phone phone = new Phone();
phone.setNumber("617-666-6666");

employee.getPhoneNumbers().add(phone);
entityManager.merge(employee);

,Q WKLV H[DPSOH ZH DOORFDWH D Phone DQG DGG LW WR DQ Employee¦V OLVW RI SKRQH QXPEHUV
:H WKHQ FDOO merge() ZLWK WKH HPSOR\HH DQG VLQFH ZH KDYH WKH MERGE CascadeType VHW
RQ WKLV UHODWLRQVKLS WKH SHUVLVWHQFH SURYLGHU ZLOO VHH WKDW LW LV D QHZ Phone HQWLW\ DQG
ZLOO FUHDWH LW ZLWKLQ WKH GDWDEDVH
5HPHPEHU WKDW RQO\ WKH JUDSK UHWXUQHG E\ WKH PHUJH RSHUDWLRQ LV LQ PDQDJHG VWDWH
QRW WKH RQH SDVVHG DV D SDUDPHWHU

REMOVE
REMOVE LV VWUDLJKWIRUZDUG ,Q RXU Employee H[DPSOH LI \RX GHOHWH DQ Employee HQWLW\ LWV
DGGUHVV ZLOO EH GHOHWHG DV ZHOO
Employee employee = entityManager.find(Employee.class, id);
entityManager.remove(employee); // Also removes the address

REFRESH
REFRESH LV VLPLODU WR MERGE 8QOLNH PHUJH WKRXJK WKLV CascadeType RQO\ SHUWDLQV WR
ZKHQ EntityManager.refresh() LV FDOOHG 5HIUHVKLQJ GRHVQ¦W XSGDWH WKH GDWDEDVH ZLWK
FKDQJHV LQ WKH REMHFW LQVWDQFH ,QVWHDG LW UHIUHVKHV WKH REMHFW LQVWDQFH¦V VWDWH IURP WKH
GDWDEDVH $JDLQ WKH FRQWDLQHG UHODWHG HQWLWLHV ZRXOG DOVR EH UHIUHVKHG
Employee employee = entityManager.find(Employee.class, id);
entityManager.refresh(employee); // address would be refreshed too

6R LI FKDQJHV WR WKH Employee¦V DGGUHVV ZHUH FRPPLWWHG E\ D GLIIHUHQW WUDQVDFWLRQ WKH


DGGUHVV SURSHUW\ RI WKH employee YDULDEOH ZRXOG EH XSGDWHG ZLWK WKHVH FKDQJHV 7KLV
LV XVHIXO LQ SUDFWLFH ZKHQ DQ HQWLW\ EHDQ KDV VRPH SURSHUWLHV WKDW DUH JHQHUDWHG E\ WKH
GDWDEDVH E\ WULJJHUV IRU H[DPSOH <RX FDQ UHIUHVK WKH HQWLW\ WR UHDG WKRVH JHQHUDWHG
SURSHUWLHV ,Q WKLV FDVH EH VXUH WR PDNH WKRVH JHQHUDWHG SURSHUWLHV UHDG RQO\ IURP D
SHUVLVWHQFH SURYLGHU SHUVSHFWLYH L H XVLQJ WKH @Column (insertable=false,
updatable=false)

ALL
ALL LV D FRPELQDWLRQ RI DOO RI WKH SUHYLRXV SROLFLHV DQG LV XVHG IRU WKH SXUSRVHV RI
VLPSOLFLW\

Cascading | 193
When to Use Cascading
<RX GRQ¦W DOZD\V ZDQW WR XVH FDVFDGLQJ IRU HYHU\ UHODWLRQVKLS \RX KDYH )RU LQVWDQFH
\RX ZRXOG QRW ZDQW WR UHPRYH WKH UHODWHG Computer RU TaskV ZKHQ UHPRYLQJ DQ
Employee HQWLW\ IURP WKH GDWDEDVH EHFDXVH WKHVH HQWLWLHV KDYH D OLIH VSDQ WKDW LV XVXDOO\
ORQJHU WKDQ WKH HPSOR\HH <RX PLJKW QRW ZDQW WR FDVFDGH PHUJHV EHFDXVH \RX PD\
KDYH IHWFKHG VWDOH GDWD IURP WKH GDWDEDVH RU VLPSO\ QRW ILOOHG WKH UHODWLRQVKLS LQ RQH
SDUWLFXODU EXVLQHVV RSHUDWLRQ )RU SHUIRUPDQFH UHDVRQV \RX PD\ DOVR QRW ZDQW WR UH
IUHVK DOO WKH UHODWLRQVKLSV DQ HQWLW\ KDV EHFDXVH WKLV ZRXOG FDXVH PRUH URXQG WULSV WR
WKH GDWDEDVH %H DZDUH KRZ \RXU HQWLWLHV ZLOO EH XVHG EHIRUH GHFLGLQJ RQ WKH FDVFDGH
W\SH ,I \RX DUH XQVXUH RI WKHLU XVH WKHQ \RX VKRXOG WXUQ RII FDVFDGLQJ HQWLUHO\ DQG
HQDEOH LW RQ D SHU FDVH EDVLV 5HPHPEHU FDVFDGLQJ LV VLPSO\ D FRQYHQLHQW WRRO IRU
UHGXFLQJ WKH EntityManager $3, FDOOV ,W¦V YHU\ HDV\ WR WULJJHU H[SHQVLYH GDWDEDVH FDOOV
ZKLFK PD\ UHVXOW LQ XQQHFHVVDU\ PXOWLWDEOH MRLQV

194 | Chapter 11:—Entity Relationships

You might also like