The document discusses Java Persistence API (JPA), which was created to address issues mapping objects to relational databases. It provides an overview of key JPA concepts like the persistence.xml file, entity definitions using annotations, identity and reference strategies for primary keys, relationships like one-to-one and many-to-many, handling orphan removal, and common errors like the transient object exception. The document also covers more advanced topics such as entity hierarchies with different mapping types, embedded objects, and best practices for using an entity manager factory.
The document discusses Java Persistence API (JPA), which was created to address issues mapping objects to relational databases. It provides an overview of key JPA concepts like the persistence.xml file, entity definitions using annotations, identity and reference strategies for primary keys, relationships like one-to-one and many-to-many, handling orphan removal, and common errors like the transient object exception. The document also covers more advanced topics such as entity hierarchies with different mapping types, embedded objects, and best practices for using an entity manager factory.
The document discusses Java Persistence API (JPA), which was created to address issues mapping objects to relational databases. It provides an overview of key JPA concepts like the persistence.xml file, entity definitions using annotations, identity and reference strategies for primary keys, relationships like one-to-one and many-to-many, handling orphan removal, and common errors like the transient object exception. The document also covers more advanced topics such as entity hierarchies with different mapping types, embedded objects, and best practices for using an entity manager factory.
Mini Book Mini Book Hebert Coelho Byron Kiourtzoglou JPA Mini Book www.javacodegeeks.com Table of Contents Reasons that led to the creation of JPA ...................................................................................................... 3 What is JPA? What is a JPA Imlementation? ........................................................................................... ! What is the ersistence."ml file #sed for? And its config#rations? ........................................................... $ %ntit& definitions. What are the 'ogic and Ph&sical annotations? ............................................................. ( Id )eneration* +efinition, #sing Identit& or -e.#ence ............................................................................ /0 Identit& ................................................................................................................................................. // -e.#ence .............................................................................................................................................. /1 Id )eneration* 2a3le)enerator and A#to ................................................................................................ /3 2a3le)enerator .................................................................................................................................... /3 A#to ..................................................................................................................................................... /$ -imle 4omosite 5e& ............................................................................................................................ /$ 6Id4lass ............................................................................................................................................. /$ 6%m3edda3le ..................................................................................................................................... /( 4omle" 4omosite 5e& ......................................................................................................................... 10 7ow to get an %ntit&Manager .................................................................................................................. 1! Maing two or more ta3les in one entit& ............................................................................................... 1$ Maing 7ierarch&* Maed-#erclass .................................................................................................. 1$ Maing 7ierarch&* -ingle 2a3le ............................................................................................................ 18 Maing 7ierarch&* Joined ...................................................................................................................... 19 Maing 7ierarch&* 2a3le er 4oncrete 4lass ........................................................................................ 3/ Pros:4ons of each hierarch& maing aroach ...................................................................................... 33 %m3edded ;3jects ................................................................................................................................... 3! %lement4ollection < how to ma a list of val#es into a class .................................................................. 3$ ;ne2o;ne #nidirectional and 3idirectional ............................................................................................. 3= >nidirectional ...................................................................................................................................... 3= Bidirectional ........................................................................................................................................ 3( 2here is no s#ch ?a#to relationshi@ ........................................................................................................ 3( ;ne2oMan&:Man&2o;ne #nidirectional and 3idirectional ..................................................................... 39 2here is no s#ch ?a#to relationshi@ ........................................................................................................ !0 Man&2oMan& #nidirectional and 3idirectional ........................................................................................ !0 2here is no s#ch ?a#to relationshi@ ........................................................................................................ !3 Man&2oMan& with e"tra fields ................................................................................................................ !3 7ow the 4ascade f#nctionalit& works? 7ow sho#ld a develoer #se the ;rhanRemoval? 7andling the org.hi3ernate.2ransient;3ject%"cetion .................................................................................................. != ;rhanRemoval ................................................................................................................................... $3 7ow to delete an entit& with relationshis. 4larif& which relationshis are raising the e"cetion ......... $! 4reating one %ntit&ManagerAactor& 3& alication ................................................................................ $$ >nderstanding how the 'aB&:%ager otion works ................................................................................... $= 7andling the ?cannot sim#ltaneo#sl& fetch m#ltile 3ags@ error ............................................................ $8 1 of =0 JPA Mini Book www.javacodegeeks.com Reasons that led to the creation of JPA One of the problems of Object Orientation is how to map the objects as the database requires. It is possible to have a class with the name Car but its data is persisted in a table named TB_CAR. The table name is just the beinnin of the problem! what if the Car class has the attribute "name# but in the database $ou find the column %TR_&A'(_CAR) The basic *ava framewor+ to access the database is *,BC. -nfortunatel$! with *,BC! a lot of hand wor+ is needed to convert a database quer$ result into *ava classes. In the code snippet bellow we demonstrate how to transform a *,BC quer$ result into Car objects. import java.sql.*; import java.util.LinkedList; import java.util.List;
public class MainWithJDBC { public static void main(String! args" throws #$%e&ti'n { Class.('r)ame(*'rg.hsqld+.jd+%Driver*";
while(rs.ne$t(""{ Car %ar , new Car("; %ar.set3d(rs.get3nt(*3d*""; %ar.set)ame(rs.getString(*)ame*""; %ars.add(%ar"; 9
for (Car %ar : %ars" { S0stem.'ut.&rintln(*Car id: * ; %ar.get3d(" ; * Car )ame: * ; %ar.get)ame(""; 9
%'nne%ti'n.%l'se("; 9 9 As $ou can understand there is a lot of boilerplate code involved usin this approach. *ust imaine the Car class the have not two but thirt$ attributes/ To ma+e thins even worse! imaine a class with 01 attributes and with a relationship to another class that has 01 attributes also e.. a Car class ma$ maintain a list of 2erson classes 3 of =0 JPA Mini Book www.javacodegeeks.com representin the drivers of the specific car where the 2erson class ma$ have 01 attributes to be populated. Other disadvantaes of *,BC is its portabilit$. The quer$ s$nta3 will chane from one database to another. 4or e3ample with Oracle database the command RO5&-' is used to limit the amount of returned lines! whereas with %ql%erver the command is TO2. Application portabilit$ is a problematic issue when database native queries are used. There are several solutions to this +ind of problem! e.. a separate file with all quer$ code could be stored outside the application deplo$able file. 5ith this approach for each database vendor a sql specific file would be required. It is possible to find other problems when developin with *,BC li+e. update a database table and its relationships! do not leave an$ orphans records or an eas$ wa$ to use hierarch$. What is JPA? What is a JPA Implementation? *2A was created as a solution to the problems mentioned earlier. *2A allows us to wor+ with *ava classes as it provides a transparent la$er to each database specific details6 *2A will do the hard wor+ of mappin table to class structure and semantics for the developer. An eas$ definition to *2A is. "A roup of specifications 7a lot of te3ts! reulari8ations and *ava Interfaces9 to define how a *2A implementation should behave#. There are man$ *2A implementations available both free and paid! e.. :ibernate! Open*2A! (clipse;in+ and the "new born# Batoo etc. 'ost *2A implementations are free to add e3tra codes! annotations that are not present in the *2A specification! but must conform to the *2A specification scemantics. The main *2A feature to address application portabilit$ is the abilit$ to map database tables into the classes. In the followin sections we will demonstrate how it is possible to map the column of a table into a *ava class field reardless of the names of both the batabase column and *ava class field. *2A created a database lanuae named *2<; to perform database queries. The advantae of *2<; is that the quer$ can be e3ecuted in all databases. SELECT id4 name4 %'l'r4 age4 d''rs FROM Car The quer$ above could be translated to the *2<; below. ! of =0 JPA Mini Book www.javacodegeeks.com SELECT % FROM Car % &otice that the result of the quer$ above is "c#! that means! a car object and not the fields=values found in the database table. *2A will create the object automaticall$. If $ou want to see several wa$s to run a database query wth |PA cck here. *2A will be responsible to translate the *2<; quer$ to the database native quer$6 the developer will not need to worr$ about which is the required sql database s$nta3. What is the persistence.xml file used for? And its configurations? The persistence.3ml file is responsible for all *2A evironment confiuration6 it can hold database! application and *2A implementation specific confiuration. In the persistence.3ml code presented here we use the (clipse;in+ *2A implementation specific confiuration! but the concept and the theor$ applied to the *ava classes in this post can be applied when usin an$ *2A implementation framewro+ available. The persistence.3ml file must be located in a '(TA>I&4 folder in the same path as the *ava classes. Below is a picture that shows where the file should be placed. This picture is valid when usin (clipse I,(. 4or &etbeans it is necessar$ to chec+ its documentation as of where the correct place to put the file is. If $ou ot the error messae. "Could not find an$ '(TA>I&4=persistence.3ml file in the classpath# here are some tips that $ou can chec+. Open the generated WAR fe and check f the persstence.xm s ocated at "/WEB- INF/casses/META-INF/". If the fe s automatcay generated and s not there your error s at the WAR creaton, you need to put the persstence.xm fe where the IDE expects. If the artfact $ of =0 JPA Mini Book www.javacodegeeks.com creaton s done manuay check the creaton scrpt (ant, maven). If your pro|ect s depoyed wth EAR fe check f the persstence.xm fe s n the E|B |ar root. If the fe s automatcay generated and s not there your error s at the WAR creaton, you need to put the persstence.xm fe where the IDE expects. If the artfact creaton s manuay check the creaton scrpt (ant, maven). If your pro|ect s a |SE pro|ect (desktop) you shoud check f the fe s not n the foder "META- INF". As defaut behavor the |PA w search n the |AR root for the foder and fe: "/META- INF/persstence.xm". Check f the fe has the name: "persstence.xm". The fe must have the name wth a etters n owercase. If *2A cannot find the file the error above will be displa$ed. As a eneral rule! it is a ood practice to put the file as displa$ed above. Chec+ below a sample of persistence.3ml. 7<xml versi'n,*=.>* en%'ding,*?15@A*<8
7properties8 7property name,*java$.&ersisten%e.jd+%.url* value,*jd+%:&'stgresql:--l'%alh'st-J&a.elati'nshi&s* -8 7property name,*java$.&ersisten%e.jd+%.driver* value,*'rg.&'stgresql.Driver* -8 7property name,*java$.&ersisten%e.jd+%.user* value,*&'stgres* -8 7property name,*java$.&ersisten%e.jd+%.&assC'rd* value,*&'stgres* -8 7J@@ 7&r'&ert0 name,*e%li&selink.ddl@generati'n* value,*dr'&@and@%reate@ta+les* -8 @@8 7property name,*e%li&selink.ddl@generati'n* value,*%reate@ta+les* -8 7J@@ 7&r'&ert0 name,*e%li&selink.l'gging.level* value,*53)#S1* -8 @@8 7-properties8 7-persistence-unit8 7-persistence8 About the code above. <persstence-unt name="MyPU" => wth ths confguraton t s possbe to defne the Persstence Unt name. The Persstence Unt can be understood as the |PA unverse of your appcaton. It contans nformaton about a casses, reatonshps, keys and others confguratons a reatng the database to your appcaton. It s possbe to add more than one Persstence Unt at the same persstence.xm fe as dspayed n the code above. transacton-type="RESOURCE_LOCAL" => Defne the transacton type. Two vaues are aowed here: RESOURCE_LOCAL and |TA. For desktop appcatons RESOURCE_LOCAL shoud be use; for web appcaton both vaues can be used, the correct vaue depends on the appcaton desgn. <provder>org.ecpse.persstence.|pa.PersstenceProvder</provder> => Defnes the |PA mpementaton provder. The provder s the appcaton |PA mpementaton. If your appcaton s usng Hbernate, the provder vaue shoud be "org.hbernate.e|b.HbernatePersstence" and for Open|PA "org.apache.open|pa.persstence.PersstenceProvderImp". <cass></cass> => Used to decare the |ava casses. In a |EE/|SE usuay ths s not requred; e.g. for a Hbernate desktop appcaton there s no need to decare the casses wth ths tags, but wth EcpseLnk and Open|PA requres the presence of the cass tag. <excude-unsted-casses>true</excude-unsted-casses> => ths confguratons defnes that f a cass s not sted n the persstence.xm t shoud not be handed as an entty (we w see more about entty n the next page) n the Persstence Unt. Ths confguraton s very usefu for appcatons wth more than one Persstence Unts, where an Entty shoud appear n one database but not n the other. It s possbe to comment a code use the tag <!- -> <propertes> => It s possbe to add specfc |PA mpementatons confguratons. Vaues ke drver, password and user t s norma to fnd t to a mpementatons; usuay these vaues are wrtten n the persstence.xm fe for a RESOUCE_LOCAL appcaton. To |TA appcatons the datasources are used by the contaners. A datasource can be specfed wth the tags <|ta-data- 8 of =0 JPA Mini Book www.javacodegeeks.com source></|ta-data-source><non-|ta-data-source></non-|ta-data-source>. Some |Boss versons requre the data source decaraton to be present even f the connecton s oca. Two confguratons are worth mentonng: Configurations Implementation Used for ecpsenk.dd-generaton EcpseLnk W actvate the automatcay database tabe creaton, or |ust vadate the database schema aganst the |PA confguraton. hbernate.hbm2dd.auto Hbernate open|pa.|dbc.SynchronzeMappngs Open|PA ecpsenk.oggng.eve EcpseLnk W defne the LOG eve of the |PA mpementaton. org.hbernate.SOL.eve=FINEST org.hbernate.type.eve=FINEST Hbernate open|pa.Log Open|PA On the nternet you w fnd the aowed vaues to each mpementaton. Entity definitions. What are the Logic and Physical annotations? 4or *2A to correctl$ map database tables into *ava classes the concept of (ntit$ was created. An (ntit$ must be created to support the same database table structure6 thus *2A handles table data modification throuh an entit$. 4or a *ava class to be considerate an (ntit$ it must follow the rules below. To be annotated wth @Entty A pubc constructor wthout arguments The |ava cass w need to have a fed wth the @Id annotaton The class below follows all the requirements to be considerate an entit$. import java$.&ersisten%e.#ntit0; import java$.&ersisten%e.3d;
K#ntit0 public class Car {
( of =0 JPA Mini Book www.javacodegeeks.com public Car("{
9
public Car(int id"{ this.id , id; 9
-- Just t' sh'C that there is n' need t' have get-set Chen Ce talk a+'ut JGH 3d K3d private int id;
private String name;
public String get)ame(" { return name; 9
public void set)ame(String name" { this.name , name; 9 9 About the code above. The cass has the annotaton @Entty above ts name There s an attrbute consdered the d of the cass that s annotated wth @Id. Every entity must have an id. Usuay ths fed s a sequenta nteger fed, but t can be a Strng or other aowed vaues Notce that there s no get/set for the d attrbute. For |PA s concdered that an entty's d s mmutabe, so there s no need to edt the d vaue. The presence of a pubc constructor wthout arguments s mandatory. Other constructors may be added As shown in the code snippet above we onl$ used two annotations! one to define an entit$ and another to declare the ?id? field6 b$ default *2A will loo+ for a table named CAR in the database with columns named I, and &A'(. B$ default *2A will use the class name and the class attribute names to find the tables and its structures. Accordin to the boo+ "2ro *2A @# we can define the *2A annotations in two wa$s. ;oical annotations and 2h$sical annotations. The ph$sical annotations will map the confiuration of the database into the class. The loical annotations will define the application modelin. Chec+ the code below. import java.util.List;
import java$.&ersisten%e.*;
K#ntit0 K1a+le(name , *1BFG#.S6)F>BADL*" 9 of =0 JPA Mini Book www.javacodegeeks.com public class Gers'n {
K3d KMeneratedNalue(strateg0 , Menerati'n10&e.H?16" private int id;
public void set)ame(String name" { this.name , name; 9 9 In the code snippet above the followin annotations are shown. A(ntit$! AId and AOneTo'an$ 7we will see about this annotation later96 these are considered loical annotations. &otice that these annotations do not define an$thin related to database! but define how a *ava class will behave as an (ntit$. Additionall$ in the code above we demonstrate another set of annotations. ATable! AColumn and ABasic. These annotations will create the relationship between the database table and the entit$. It is possible to define the table name! column name and other information reardin the database. This +ind of annotations are +nown as 2h$sical annotations! it is their job to "connect# the database to the *2A code. Its out of the scope of this mini boo+ to present ever$ annotation supported b$ *2A! but it is ver$ eas$ to find this information on the internet6 e... @Column(name = PERSON_NAME len!th = "## uni$ue = true nulla%le = &alse'. The ph$sical annotations are the easier to understand because it loo+s li+e database confiuration. Id Generation !efinition" using Identity or #e$uence As said in previous chapters! ever$ entit$ must have an id. *2A has the option to automaticall$ enerate the entit$ id. There are three options for automatic id eneration. Identty Sequence TabeGenerator /0 of =0 JPA Mini Book www.javacodegeeks.com 5e must have in mind that ever$ database has its own id eneration mechanism. Oracle and 2ostres databases use the %equence approach! %ql%erver and '$%<; use the Identit$ approach. It is not possible to use an id eneration approach in a server when the server does not support it. The followin *ava t$pes are allowed to be used for an id attribute. b$te=B$te! int=Inteer! short=%hort! lon=;on! char=Character! %trin! BiInteer! java.util.,ate and java.sql.,ate. Identity This is the simplest id eneration approach. *ust annotate the id field li+e below. import java$.&ersisten%e.#ntit0; import java$.&ersisten%e.MeneratedNalue; import java$.&ersisten%e.Menerati'n10&e; import java$.&ersisten%e.3d;
K#ntit0 public class Gers'n {
K3d KMeneratedNalue(strateg0 , Menerati'n10&e.3D#)131P" private int id;
private String name;
public String get)ame(" { return name; 9
public void set)ame(String name" { this.name , name; 9 9 The database controls the I, eneration! *2A does not act on the id at all. Thus in order to retrieve the id from the databse an entit$ needs to be persisted first! and after the transaction commits! a quer$ is e3ecuted so as to retrieve the enerated id for the specific entit$. This procedure leads to a small performance deradation! but not somethin troublesome. The aforementioned id eneration approach does not allow allocatin ids in memor$. 5e will e3amine what this ids allocation means in the followin chapters. // of =0 JPA Mini Book www.javacodegeeks.com #e$uence The %equence approach can be confiured li+e below. import java$.&ersisten%e.#ntit0; import java$.&ersisten%e.MeneratedNalue; import java$.&ersisten%e.Menerati'n10&e; import java$.&ersisten%e.3d; import java$.&ersisten%e.Sequen%eMenerat'r;
K#ntit0 KSequen%eMenerat'r(name , Car.CH.FS#/?#)C#F)HM#4 sequen%e)ame , Car.CH.FS#/?#)C#F)HM#4 initialNalue , =>4 all'%ati'nSiQe , RD" public class Car {
public static final String CH.FS#/?#)C#F)HM# , *CH.FS#/?#)C#F3D*;
K3d KMeneratedNalue(strateg0 , Menerati'n10&e.S#/?#)C#4 generat'r , CH.FS#/?#)C#F)HM#" private int id;
private String name;
public String get)ame(" { return name; 9
public void set)ame(String name" { this.name , name; 9 9 About the code above. The @SequenceGenerator annotaton w defne that there w be a sequence n the database wth the specfed name (sequenceName attrbute). The same sequence coud be shared between enttes but s not recomended. If we use the Car sequence n the House entty, the d vaues n the tabes woud not be sequenta; when the frst car s perssted the d woud be 1, f another car s perssted the d woud be 2; when the frst house s perssted ts d woud be 3, ths w happen f the House entty uses the same sequence as the Car entty. The attrbute "name = Car.CAR_SEOUENCE_NAME" defnes the name of the sequence nsde the appcaton. Sequence decaraton shoud be done ony once. A Enttes that w use the same sequence w |ust have to use the specfc sequence name. That s why we assgn the sequence name vaue to a statc attrbute at the specfc entty. The vaue "sequenceName = Car.CAR_SEOUENCE_NAME" refects the sequence name at the database eve. The "ntaVaue = 10" defnes the frst d vaue of the sequence. A deveoper must be cautous /1 of =0 JPA Mini Book www.javacodegeeks.com wth ths confguraton; f after nsertng the frst row the appcaton s restarted, |PA w try to nsert a new entty wth the same vaue defned n the ntaVaue attrbute. An error message w be dspayed ndcatng that the d s aready n use. "aocatonSze = 53" represents the amount of ds that |PA w store n cache. Works ke ths: when the appcaton s started |PA w aocate n memory the specfed number of ds and w share these vaues to each new perssted entty. In the code above, the ds woud go from 10 (ntaVaue) up to 63 (ntaVaue + aocatonSze). When the number of aocated ds ends |PA w request from the database and aocate n memory 53 more ds. Ths act of aocatng ds nto memory s a good approach to optmze server memory, snce |PA w not need to trgger the database wth every nsert so as to get the created d |ust ke wth the @Identty approach. The @GeneratedVaue(strategy = GeneratonType.SEOUENCE, generator = CAR_SEOUENCE_NAME) annotaton defnes that the generaton type as SEOUENCE and the name of the generator. Id Generation %a&leGenerator and Auto %a&leGenerator The te3t below describes how the TableBenerator wor+s. A tabe s used to store the d vaues Ths tabe has a coumn that w store the tabe name and the actua d vaue So far, ths s the ony Generaton ID approach that aows database portabty, wthout the need of aterng the d generaton approach. Imagne an appcaton that s runnng wth Postgres and uses a Sequence. If we were to use the same appcaton wth SqServer too we woud have to create two dstnct artfacts (WAR/|AR/EAR) of t, one for each database - snce SqServer doen not support Sequences. Wth the TabeGenerator approach the same artfact can be used for both databases. Chec+ the code below to see how the TableBenerator approach can be used. import java$.&ersisten%e.*;
K#ntit0 public class Gers'n {
K3d K1a+leMenerat'r(name,*1HBL#FM#)#.H16.*4 ta+le,*3DF1HBL#*4 &kC'lumn)ame,*3DF1HBL#F)HM#*4 &kC'lumnNalue,*G#.S6)F3D*4 valueC'lumn)ame,*3DF1HBL#FNHL?#*" KMeneratedNalue(strateg0 , Menerati'n10&e.1HBL#4 generat'r,*1HBL#FM#)#.H16.*" /3 of =0 JPA Mini Book www.javacodegeeks.com private int id;
private String name;
public String get)ame(" { return name; 9
public void set)ame(String name" { this.name , name; 9 9 The code above will use the table in the imae below 7it is possible to confiure *2A to create the specific table automaticall$! just add the needed confiuration as presented in the section about persistence.3ml9. About the code above. ?name" => Is the TabeGenerator d nsde the appcaton. ?tabe" => Name of the tabe that w hod the vaues. ?pkCoumnName" => Coumn name that w hod the d name. In the code above the coumn name "d_tabe_name" w be used. ?vaueCoumnName" => Coumn name that w hod the d vaue. ?pkCoumnVaue" => Tabe name that w persst n the tabe. The defaut vaue s the entty name + d (entty attrbute defned as d). In the code above w be PERSON_ID that s the same vaue descrbed above. ntaVaue, aocatonSze => These optons can be used n the @TabeGenerator annotaton aso. Check the Sequence approach secton above to see how they shoud be used. It s possbe to decare TabeGenerator across dfferent enttes wthout the probem of oosng sequenced ds (ke the Sequence probem that we saw earyer). The best practice to use the table enerator declartion is in an orm.3ml file. This file is used to override *2A confiuration throuh annotations and is out of the scope of this mini boo+. /! of =0 JPA Mini Book www.javacodegeeks.com Auto The Auto approach 7automaticall$9 allows *2A to choose an approach to use. This is the default value and can be used li+e below. K3d KMeneratedNalue(strateg0 , Menerati'n10&e.H?16" -- 'r just KMeneratedNalue private int id; 5ith the Auto approach an$ strate$ can be used b$ *2A. *2A will choose between the 0 approaches discussed earl$er. #imple 'omposite (ey A simple +e$ is when the id uses just one field. A simple +e$ is used li+e below. A composite +e$ is needed when more than one attribute is required as an entit$ id. It is possible to find simple composite +e$ and comple3 composite +e$. 5ith a %imple composite +e$ use onl$ plain *ava attributes for the id 7e. %trin! int! /9. In the followin sections we will disquas all about comple3 composite +e$ semantics. There are two wa$s to map a simple composite +e$! with AIdClass or A(mbeddedId. )Id'lass Chec+ the code below. import java$.&ersisten%e.*;
K#ntit0 K3dClass(Car3d.class" public class Car {
K3d private int serial;
K3d private String +rand;
/$ of =0 JPA Mini Book www.javacodegeeks.com private String name;
public String get)ame(" { return name; 9
public void set)ame(String name" { this.name , name; 9
public int getSerial(" { return serial; 9
public void setSerial(int serial" { this.serial , serial; 9
public String getBrand(" { return +rand; 9
public void setBrand(String +rand" { this.+rand , +rand; 9 9 About the code above6 @IdCass(CarId.cass) => ths annotaton ndcates that the CarId has nsde of t the d attrbutes found n the Car entty. A feds annotated wth @Id must be found n the IdCass. It s possbe to use the @GeneratedVaue annotaton wth ths knd of composte key. For exampe n the code above t woud be possbe to use the @GeneratedVaue wth the "sera" attrbute. Chec+ below the CarId class code. import java.i'.SerialiQa+le;
public class Car3d implements SerialiQa+le{
private static final lon serialNersi'n?3D , DSDL;
private int serial; private String +rand;
-- must have a de(ault %'nstru%'t public Car3d(" {
9
/= of =0 JPA Mini Book www.javacodegeeks.com public Car3d(int serial4 String +rand" { this.serial , serial; this.+rand , +rand; 9
public int getSerial(" { return serial; 9
public String getBrand(" { return +rand; 9
-- Must have a hashC'de meth'd K6verride public int hashC'de(" { return serial ; +rand.hashC'de("; 9
-- Must have an equals meth'd K6verride public boolean equals(6+je%t '+j" { if ('+j instanceof Car3d" { Car3d %ar3d , (Car3d" '+j; return %ar3d.serial ,, this.serial TT %ar3d.+rand.equals(this.+rand"; 9
return false; 9 9 The class CarId has the fields listed as AId in the Car entit$. To use a class as I, it must follow the rules below. A pubc constructor wth no arguments must be found Impements the Serazabe nterface Overwrte the hashCode/equas method To do a quer$ aainst a database to find an entit$ iven a simple composite +e$ just do li+e below. #ntit0Manager em , -- get valid entit0 manager
Car3d %ar3d , new Car3d(DD4 *5'rd*";
Car &ersistedCar , em.(ind(Car.class4 %ar3d";
S0stem.'ut.&rintln(&ersistedCar.get)ame(" ; * @ * ; &ersistedCar.getSerial(""; To use the find method it is necessar$ to provide the id class with the required information. /8 of =0 JPA Mini Book www.javacodegeeks.com )Em&edda&le The other approach to use the composite +e$ is presented below. import java$.&ersisten%e.*;
K#ntit0 public class Car {
K#m+edded3d private Car3d %ar3d;
private String name;
public String get)ame(" { return name; 9
public void set)ame(String name" { this.name , name; 9
public Car3d getCar3d(" { return %ar3d; 9
public void setCar3d(Car3d %ar3d" { this.%ar3d , %ar3d; 9 9 About the code above. The d cass was wrtten nsde the Car cass. The @EmbeddedId s used to defne the cass as an d cass. There s no need to use the @Id annotaton anymore. The class id will be li+e below. import java.i'.SerialiQa+le;
import java$.&ersisten%e.#m+edda+le;
K#m+edda+le public class Car3d implements SerialiQa+le{
private static final lon serialNersi'n?3D , DSDL;
private int serial; private String +rand;
/( of =0 JPA Mini Book www.javacodegeeks.com -- must have a de(ault %'nstru%'t public Car3d(" {
-- Must have a hashC'de meth'd K6verride public int hashC'de(" { return serial ; +rand.hashC'de("; 9
-- Must have an equals meth'd K6verride public boolean equals(6+je%t '+j" { if ('+j instanceof Car3d" { Car3d %ar3d , (Car3d" '+j; return %ar3d.serial ,, this.serial TT %ar3d.+rand.equals(this.+rand"; 9
return false; 9 9 About the code above. The @Embeddabe annotaton aows the cass to be used as d. The feds nsde the cass w be used as ds. To use a class as I, it must follow the rules below. A pubc constructor wth no arguments must be found Impements the Serazabe nterface Overwrte the hashCode/equas method It is possible to do queries with this +ind of composite +e$ just li+e the AIdClass presented above. /9 of =0 JPA Mini Book www.javacodegeeks.com 'omplex 'omposite (ey A comple3 composite +e$ is composed of other entities C not plain *ava attributes. Imaine an entit$ ,o:ouse where it uses the ,o as the id. Ta+e a loo+ at the code below. import java$.&ersisten%e.*;
public String getBrand(" { 10 of =0 JPA Mini Book www.javacodegeeks.com return +rand; 9
public void setBrand(String +rand" { this.+rand , +rand; 9 9 About the code above. The @Id annotaton s used n the entty DogHouse to nform |PA that the DogHouse w have the same d as the Dog. We can combne the @Id annotaton wth the @OneToOne annotaton to dctate that there s an expct reatonshp between the casses. More nformaton about the @OneToOne annotaton w be avaabe ater on. Imaine a scenario where it is required to access the ,o:ouse id without passin throuh the class ,o 7do:ouse.et,o79.etId799. *2A has a wa$ of doin it without the need of the Demeter Law pattern. import java$.&ersisten%e.*;
public void setBrand(String +rand" { this.+rand , +rand; 9
public int getD'g3d(" { return d'g3d; 1/ of =0 JPA Mini Book www.javacodegeeks.com 9
public void setD'g3d(int d'g3d" { this.d'g3d , d'g3d; 9 9 About the code above. There s an expct fed mapped wth @Id. The Dog entty s mapped wth the @MapsId annotaton. Ths annotaton ndcates that |PA w use the Dog.Id as the DogHouse.DogId (|ust ke before); the dogId attrbute w have the same vaue as the dog.getId() and ths vaue w be attrbuted at run tme. dogId fed does not need to be expctey mapped to a database tabe coumn. When the appcaton starts |PA w attrbute the dog.getId() to the dogId attrbute. To finish this subject! let us see one more topic. :ow can we map an entit$ id with more than one entities) Chec+ the code below. import java$.&ersisten%e.*;
K#ntit0 K3dClass(D'gU'use3d.class" public class D'gU'use {
-- get and set 9 About the code above. Notce that both enttes (Dog and Person) were annotated wth @Id. The annotaton @IdCass s used to ndcate the need of a cass to map the d. import java.i'.SerialiQa+le;
public class D'gU'use3d implements SerialiQa+le{ 11 of =0 JPA Mini Book www.javacodegeeks.com
private static final lon serialNersi'n?3D , =L;
private int &ers'n; private int d'g;
public int getGers'n(" { return &ers'n; 9
public void setGers'n(int &ers'n" { this.&ers'n , &ers'n; 9
public int getD'g(" { return d'g; 9
public void setD'g(int d'g" { this.d'g , d'g; 9
K6verride public int hashC'de(" { return &ers'n ; d'g; 9
return false; 9 9 About the code above. The cass has the same amount of attrbutes as the number of attrbutes n the cass DogHouse annotated wth @Id Notce that the attrbutes nsde the DogHouseId have the same name as the attrbutes nsde the DogHouse annotated wth @Id. Ths s mandatory for |PA to correcty utze d functonaty. For exampe If we named the Person type attrbute nsde the DogHouse cass as "dogHousePerson" the name of the Person type attrbute nsde the DogHouseId cass woud have to change aso to "dogHousePerson". To use a class as I, it must follow the rules below. A pubc constructor wth no arguments must be found 13 of =0 JPA Mini Book www.javacodegeeks.com Impements the Serazabe nterface Overwrte the hashCode/equas method *o+ to get an Entity,anager There are two wa$s to et an (ntit$'anaer. One is with injection and the other throuh a factor$. The easiest wa$ to et an (ntit$'anaer is with injection! the container will inject the (ntit$'anaer. Below is how the injection code wor+s. KGersisten%eC'nte$t(unit)ame , *G#.S3S1#)C#F?)31FMHGG#DF3)F1U#FG#.S3S1#)C#FEML*" private #ntit0Manager entit0Manager; It is needed to annotate the (ntit$'anaer field with. "A2ersistenceConte3t7unit&ame D "2(R%I%T(&C(_-&IT_'A22(,_I&_T:(_2(R%I%T(&C(_E';#9#. The injection option will onl$ wor+ for *(( applications! runnin inside applications servers li+e *Boss! Blassfish/ To achieve the injection without problems the persistence.3ml must be in the riht place! and must have 7if needed9 a datasource defined. The (ntit$'anaer injection! until toda$! will wor+ onl$ with a server that supports an (*B container. Tomcat and other 5(B=%ervlet onl$ containers will not inject it. 5hen the application is a *%( 7des+top9 application or when a web application wants to handle the database connection manuall$ just use the code bellow. #ntit0Manager5a%t'r0 em( , Gersisten%e.%reate#ntit0Manager5a%t'r0(*G#.S3S1#)C#F?)31FMHGG#DF3)F1U#FG#.S3S1#)C#FEML*"; #ntit0Manager entit0Manager , em(.%reate#ntit0Manager(";
entit0Manager.get1ransa%ti'n(".+egin(";
-- d' s'mething
entit0Manager.get1ransa%ti'n(".%'mmit("; entit0Manager.%l'se("; &otice that it is required to et an instance of the (ntit$'anaer4actor$ first! which will be lin+ed to a 2ersistence-nit created in the persistence.3ml file. Throuh the (ntit$'anaer4actor$ is possible to et an instance of the (ntit$'anaer. 1! of =0 JPA Mini Book www.javacodegeeks.com ,apping t+o or more ta&les in one entity A class ma$ have information in more than one table. To map an (ntit$ that has its data in more than one table! just do li+e below. import java$.&ersisten%e.*;
K#ntit0 K1a+le(name,*D6M*" KSe%'ndar01a+les({ KSe%'ndar01a+le(name,*D6MFS#C6)DH.PFH*4 &kJ'inC'lumns,{KGrimar0Ve0J'inC'lumn(name,*D6MF3D*"9"4 KSe%'ndar01a+le(name,*D6MFS#C6)DH.PFB*4 &kJ'inC'lumns,{KGrimar0Ve0J'inC'lumn(name,*D6MF3D*"9" 9" public class D'g { K3d KMeneratedNalue(strateg0 , Menerati'n10&e.H?16" private int id;
private String name; private int age; private double Ceight;
-- get and set
9 About the code above. The annotaton @SecundaryTabe s used to ndcate at whch tabe the Entty data can be found. If the data s found n |ust one secondary tabe |ust the @SecundaryTabe annotaton s enough. The annotaton @SecundaryTabes s used to group up severa tabes n one cass. It groups severa @SecundaryTabe annotatons. ,apping *ierarchy ,apped#uperclass %ometimes is needed to share methods=attributes between classes6 thus create a class hierarch$. In case the super class C the one with the shared methods=attributes > is not an entit$! it is required to be mar+ed as 'apped%uperclass. Chec+ below how the 'apped%uperclass concept can be applied. import java$.&ersisten%e.Ma&&edSu&er%lass;
KMa&&edSu&er%lass 1$ of =0 JPA Mini Book www.javacodegeeks.com public abstract class D'g5ather { private String name;
public String get)ame(" { return name; 9
public void set)ame(String name" { this.name , name; 9
9 K#ntit0 K1a+le(name , *D6M*" public class D'g extends D'g5ather {
K3d KMeneratedNalue(strateg0 , Menerati'n10&e.H?16" private int id;
private String %'l'r;
public int get3d(" { return id; 9
public void set3d(int id" { this.id , id; 9
public String getC'l'r(" { return %'l'r; 9
public void setC'l'r(String %'l'r" { this.%'l'r , %'l'r; 9 9 About the code above. The DogFather cass s annotated wth the @MappedSupercass annotaton. Wth ths annotaton a DogFather chd casses w have ts attrbutes perssted n the database, but DogFather w not be mapped to a database tabe. A MappedSupercass can be an abstract or a concrete cass. The Dog cass has the ID generator, ony Dog s an entty. DogFather s not an entty. %ome recommendations about 'apped%uperclass. A MappedSupercass cannot be annotated wth @Entty\@Tabe. It s not a cass that w be 1= of =0 JPA Mini Book www.javacodegeeks.com perssted. Its attrbutes/methods w be refected n ts chd casses. It s aways a good practce to create t as abstract. A MappedSupercass w not be used n the queres. Cannot be perssted, t s not an entty. 5hen do we use it) If we do not need to use the super class in database queries! it would be a ood idea to use a 'apped%uperclass. In the opposite case it is a ood idea to use (ntit$ hierarch$ 7see the followin sections for details9. ,apping *ierarchy #ingle %a&le 5ith *2A it is possible to find different approaches for persistin class hierarchies. In an Object Orientated lanuae li+e *ava it is ver$ eas$ to find hierarch$ between classes that will have their data persisted. The %inle Table strate$ will store all hierarch$ data into one table. Chec+ the code below. import java$.&ersisten%e.*;
K#ntit0 K1a+le(name , *D6M*" K3nheritan%e(strateg0 , 3nheritan%e10&e.S3)ML#F1HBL#" KDis%riminat'rC'lumn(name , *D6MFCLHSSF)HM#*" public abstract class D'g { K3d KMeneratedNalue(strateg0 , Menerati'n10&e.H?16" private int id;
private String name;
-- get and set 9 import java$.&ersisten%e.#ntit0;
K#ntit0 KDis%riminat'rNalue(*SMHLLFD6M*" public class SmallD'g extends D'g { private String littleBark;
public String getLittleBark(" { return littleBark; 9
public void setLittleBark(String littleBark" { this.littleBark , littleBark; 9 18 of =0 JPA Mini Book www.javacodegeeks.com 9 import java$.&ersisten%e.*;
K#ntit0 KDis%riminat'rNalue(*U?M#FD6M*" public class UugeD'g extends D'g { private int hugeG''Weight;
public int getUugeG''Weight(" { return hugeG''Weight; 9
public void setUugeG''Weight(int hugeG''Weight" { this.hugeG''Weight , hugeG''Weight; 9 9 About the code above. @Inhertance(strategy = InhertanceType.SINGLE_TABLE) => ths annotaton shoud be paced n the hghest pace of the herarchy (the "father" cass), aso known as "root". Ths annotaton w defne the herarch pattern to be foowed, n the annotaton above the herarchy mappng strategy s set to Snge Tabe. @DscrmnatorCoumn(name = "DOG_CLASS_NAME") => w defne the name of the coumn that w nk a database tabe row to a cass. Check n the mage beow how the data s stored. @DscrmnatorVaue => W set the vaue to be perssted n the coumn defned n the annotaton @DscrmnatorCoumn. Check n the mage beow how the data s stored. Notce that the d s ony defned n the root cass. It s not aowed to a chd cass to decare an d. It is also possible to define the class discriminator column as inteer. @DscrmnatorCoumn(name = "DOG_CLASS_NAME", dscrmnatorType = DscrmnatorType.INTEGER) => defne the fed as nteger 1( of =0 JPA Mini Book www.javacodegeeks.com @DscrmnatorVaue("1) => The vaue to be perssted n the Entty must change, a number w be perssted nstead a text. ,apping *ierarchy Joined 5hen a hierarch$ is usin the *oined strate$ each entit$ will have its data stored in the respective table. Instead of usin just one table for all hierarch$ classes! each entit$ will have its own table. Chec+ the code below to see how *oined strate$ can be used. import java$.&ersisten%e.*;
K#ntit0 K1a+le(name , *D6M*" K3nheritan%e(strateg0 , 3nheritan%e10&e.J63)#D" KDis%riminat'rC'lumn(name , *D6MFCLHSSF)HM#*" public abstract class D'g {
K3d KMeneratedNalue(strateg0 , Menerati'n10&e.H?16" private int id;
private String name;
-- get and set 9 import java$.&ersisten%e.*;
K#ntit0 KDis%riminat'rNalue(*U?M#FD6M*" public class UugeD'g extends D'g { private int hugeG''Weight;
public int getUugeG''Weight(" { return hugeG''Weight; 9 public void setUugeG''Weight(int hugeG''Weight" { this.hugeG''Weight , hugeG''Weight; 9 9 import java$.&ersisten%e.*;
K#ntit0 KDis%riminat'rNalue(*SMHLLFD6M*" public class SmallD'g extends D'g { private String littleBark;
19 of =0 JPA Mini Book www.javacodegeeks.com public String getLittleBark(" { return littleBark; 9
public void setLittleBark(String littleBark" { this.littleBark , littleBark; 9 9 About the code above. The annotaton @Inhertance(strategy = InhertanceType.|OINED) now has the |oned vaue. Check beow how the tabes are: ,o table :ue,o table %mall,o table 30 of =0 JPA Mini Book www.javacodegeeks.com &otice in the imaes above how the data is persisted to each table. (ver$ entit$ has its information persisted across unique tables6 for this strate$ *2A will use one table per entit$ reardlessthe entit$ bein concrete or abstract. The ,o table maintains all data common to all the classes of the hierarch$6 The ,o table maintains a column indicatin to which entit$ a row belons to. ,apping *ierarchy %a&le per 'oncrete 'lass The Table 2er Concrete strate$ will create a table per concrete entit$. If an abstract entit$ is found in the hierarch$ this data will be persisted in the concrete children entities database tables. Chec+ the code below. import java$.&ersisten%e.*;
K#ntit0 K1a+le(name , *D6M*" K3nheritan%e(strateg0 , 3nheritan%e10&e.1HBL#FG#.FCLHSS" public abstract class D'g {
K3d KMeneratedNalue(strateg0 , Menerati'n10&e.H?16" private int id;
private String name;
-- get and set 9 import java$.&ersisten%e.#ntit0;
K#ntit0 public class UugeD'g extends D'g { private int hugeG''Weight;
public int getUugeG''Weight(" { return hugeG''Weight; 9
K#ntit0 3/ of =0 JPA Mini Book www.javacodegeeks.com public class SmallD'g extends D'g { private String littleBark;
public String getLittleBark(" { return littleBark; 9
public void setLittleBark(String littleBark" { this.littleBark , littleBark; 9 9 About the code above. @Inhertance(strategy = InhertanceType.TABLE_PER_CLASS) => defne the herarchy type as tabe per cass. The annotaton @DscrmnatorCoumn(name = "DOG_CLASS_NAME") s not used n the chdren casses anymore. Each concrete cass w have ts own data, |PA w not spread entty data across tabes. There s no need for the annotaton @DscrmnatorVaue for the same prncpa as above. Check beow the database tabes: :ue,o Table %mall,o Table &otice that the attributes of the ,o entit$ are persisted in the :ue,o and %mall,o table. 31 of =0 JPA Mini Book www.javacodegeeks.com Pros-'ons of each hierarchy mapping approach -nfortunatel$ there is no ?better? approach to follow! each approach has its advantaes and disadvantaes. It is necessar$ to anal$8e the pros=cons of each approach and decide which is better for the application. Approach Pros Cons SINGLE_TABLE Easer to understand the tabe mode. |ust one tabe s requred. Cannot have "non nu" feds. Imagne that SmaDog has the harCoor attrbute non nu n the database. When HugeDog get perssted an error message from the database w be receve, t w nform that harCoor cannot be nu. The enttes attrbutes can be found a n one tabe. As genera rue has a good performance. |OINED Each entty w have ts own database tabe to store the data. The nsert has a hgher performance cost. An nsert w be done to each database tabe used n the herarchy. Imagne a herarchy ke C extends B extends A, when C s perssted 3 nserts w be executed - one to each mapped entty. It w foow the OO patterns apped n the appcaton code. The |on number executed n the database queres w ncrease n deeper herarches. TABLE_PER_CLASS When the query s executed to brng |ust one entty the performance s better. A database tabe w have ony one entty data. Coumns w be repeated. The attrbutes found n the abstract enttes w repeated n the concrete chd enttes. When a query brngs more than one entty of the herarchy ths query w have a hgher cost. It w be used UNION or one query per tabe. 33 of =0 JPA Mini Book www.javacodegeeks.com Em&edded .&/ects (mbedded Objects is a wa$ to orani8e entities that have different data in the same table. Imaine a database table that maintains ?person? information 7e.. name! ae9 and address data 7street name! house number! cit$ etc9. Chec+ the picture below. It is possible to see data related to a person and their correspondin address also. Chec+ the code below to see an e3ample of how to implement the (mbedded Objects concept with the 2erson and Address entities. import java$.&ersisten%e.*;
K#m+edda+le public class Hddress { KC'lumn(name , *h'useFaddress*" private String address;
KC'lumn(name , *h'useFnum+er*" private int num+er;
public String getHddress(" { return address; 9
public void setHddress(String address" { this.address , address; 9
-- get and set 9 import java$.&ersisten%e.*;
K#ntit0 K1a+le(name , *&ers'n*" public class Gers'n {
K3d private int id; private String name; private int age; 3! of =0 JPA Mini Book www.javacodegeeks.com
K#m+edded private Hddress address;
public Hddress getHddress(" { return address; 9
public void setHddress(Hddress address" { this.address , address; 9
-- get and set 9 About the code above. The @Embeddabe annotaton (Address cass) aows the cass to be used nsde an entty, notce that Address s not an entty. It s |ust a cass to hep organze the database data. A @Coumn annotaton s used n the Address cass to ndcate the tabe database coumn name. The @Embedded annotaton (Person entty) ndcates that |PA w map a the feds that are nsde the Address cass as beongng to the Person entty. The Address cass can be used n other enttes. There are ways to overrde the @Coumn annotaton at runtme. Element'ollection 0 ho+ to map a list of 1alues into a class %ometimes it is needed to map a list of values to an entit$ but those values are not entities themselves! e.. person has emails! do has nic+names etc. Chec+ the code below that demonstrates this situation. import java.util.List; import java.util.Set;
import java$.&ersisten%e.*;
K#ntit0 K1a+le(name , *&ers'n*" public class Gers'n {
K3d KMeneratedNalue private int id; 3$ of =0 JPA Mini Book www.javacodegeeks.com private String name;
-- get and set 9 public enum CarBrands { 56.D4 53H14 S?O?V3 9 About the code above. Notce that two sts of data are used: Set<Strng>, Lst<CarBrand>. The @EementCoecton annotaton s used not wth enttes but wth "smpe" attrbutes (e.g. Strng, Enum etc). The @EementCoecton annotato s used to aow an attrbute to repeat tsef severa tmes. The @Enumerated(EnumType.STRING) annotaton s used wth the @EementCoecton annotaton. It defnes how the enum w be perssted n the database, as Strng or as Ordna (cck here to more nformaton). @CoectonTabe(name = "person_has_emas") => confgure |PA to whch tabe the nformaton w be stored. When ths annotaton s not present |PA w create a database tabe named after the cass and attrbute name by defaut. For exampe wth the "Lst<CarBrand> brands" attrbute the database tabe woud be named as "person_brands". .ne%o.ne unidirectional and &idirectional It is ver$ eas$ to find entities with relationships. A person has dos! dos have fleas! fleas has/ hum/ never mind. 2nidirectional A one to one relationship is the easiest to understand. Imaine that a 2erson has onl$ one Cellular and onl$ 2erson will "see# the Cellular! the Cellular will not see 2erson. Chec+ the imae below. 3= of =0 JPA Mini Book www.javacodegeeks.com Chec+ how the 2erson class will be. import java$.&ersisten%e.*;
-- get and set 9 About the code above. In a undrectona reatonshp |ust one sde of the reatonshp knows ("sees") the other. Notce that Person knows Ceuar but Ceuar does not know Person. It s possbe to do person.getCeuar() but t s not possbe to do ceuar.getPerson(). In the Person entty t s possbe to use the annotaton @OneToOne. Ths annotaton ndcates to |PA that there s a reatonshp between the enttes. 38 of =0 JPA Mini Book www.javacodegeeks.com (ver$ relationship needs one of the entities to be the "relationship owner#. Bein the relationship owner is nothin more than to have the forein +e$ in the database table. In the code above $ou can see that the annotation A*oinColumn has been used. This annotation indicates that the forein +e$ will be located in the person database table! ma+in the 2erson entit$ owner of the relationship. 3idirectional To transform this relationship in a bidirectional one we just have to edit the Cellular entit$. Chec+ the class below. import java$.&ersisten%e.*;
-- get and set 9 About the code above. The same annotaton @OneToOne to the Person attrbute s used n the Ceuar entty. The parameter "ma((ed)y" was used n the @OneToOnea nnotaton. Ths parameter ndcates that the entty Person s the owner of the reatonshp; the foregn key must exst nsde the person tabe, and not the Ceuar tabe. A developer must have in mind that for *2A to wor+ in an optimal wa$ it is a ood practice to leave one side of the relationship as the owner. If the annotation AOneToOne found in the Cellular entit$ was without the "mappedB$# parameter! *2A would handle the Cellular entit$ as the owner of the relationship too. It is not a ood idea to leave either sides of a relationship without definin ?mappedB$?! or both with ?mappedB$? setted. %here is no such 4auto relationship5 4or a Bidirectional relationship to wor+ correctl$ it is necessar$ to do li+e below. &ers'n.setCellular(%ellular"; %ellular.setGers'n(&ers'n"; 3( of =0 JPA Mini Book www.javacodegeeks.com *2A uses the *ava concept of class reference! a class must maintain a reference to another one if there will be a join between them. *2A will not create a relationship automaticall$6 to have the relationship in both sides it is needed to do li+e above. .ne%o,any-,any%o.ne unidirectional and &idirectional The one to man$ relationship is used when an entit$ has a relationship with a list of other entities! e.. a Cellular ma$ have several Calls but a Call can have onl$ one Cellular. The OneTo'an$ relationship is represented with a list of values! there is more than one entit$ associate with it. ;et us start with the 'an$ToOne side. import java$.&ersisten%e.*;
-- get and set 9 About the code above. The annotaton @ManyToOne s used. Notce that annotaton @|onCoumn s used to defne who the owner of the reatonshp s. The @ManyToOne sde w aways be the owner of the reatonshp. There s no way of usng the mappedBy attrbute nsde the @ManyToOne annotaton. To do a bidirectional relationship we need to edit the Cellular entit$ 7created in the previous sections9. Chec+ the code below. import java$.&ersisten%e.*;
39 of =0 JPA Mini Book www.javacodegeeks.com K#ntit0 public class Cellular {
-- get and set 9 About the code above. The @OneToMany annotaton s used. Ths annotaton must be paced n a coecton. The mappedBy drecttve s used to defne the Ca entty as the reatonshp owner. (ver$ relationship needs one of the entities to be the "relationship owner#. Bein the relationship owner is nothin more than to have the forein +e$ in the database table. In the code above $ou can see that the annotation A*oinColumn has been used. This annotation indicates that the forein +e$ will be located in the call database table! ma+in the Call entit$ owner of the relationship. %here is no such 4auto relationship5 4or a Bidirectional relationship to wor+ correctl$ it is necessar$ to do li+e below. %all.setCellular(%ellular"; %ellular.setCalls(%alls"; *2A uses the *ava concept of class reference! a class must maintain a reference to another one if there will be a join between them. *2A will not create a relationship automaticall$6 to have the relationship in both sides it is needed to do li+e above. ,any%o,any unidirectional and &idirectional In a 'an$To'an$ e3ample a person ma$ have several dos and a do ma$ have several persons 7imaine a do that lives in a house with FG persons9. In a 'an$To'an$ approach it is necessar$ to use an e3tra database table to store the ids that relate the database !0 of =0 JPA Mini Book www.javacodegeeks.com tables of ever$ entit$ of the relationship. Thus for the specific e3ample we will have a person table! a do table and a relationship table named person_do. The person_do table would onl$ maintain the person_id and do_id values that represent which do belons to which person. %ee the database table imaes below. 2erson table ,o table person_do table &otice that the person_do has onl$ ids. Chec+ the 2erson entit$ below. import java.util.List;
import java$.&ersisten%e.*;
K#ntit0 public class Gers'n {
K3d KMeneratedNalue private int id;
!/ of =0 JPA Mini Book www.javacodegeeks.com private String name;
-- get and set 9 About the code above. The @ManyToMany annotaton s used. The @|onTabe annotaton s used to set the reatonshp tabe between the enttes; "name" sets the tabe name; "|onCoumn" defnes the coumn name n the tabe of the reatonshp owner; "nverse|onCoumns" defnes the coumn name n the tabe of the non-reatonshp owner. The 2erson entit$ has unidirectional relationship with the ,o entit$. Chec+ how the ,o entit$ would loo+ li+e in a bidirectional relationship. import java.util.List;
-- get and set 9 As $ou can see the A'an$To'an$ annotation is confiured with the ?mappedB$? option! which establishes the 2erson entit$ as the relationship owner. (ver$ relationship needs that one of the entities be the "relationship owner#. 4or the 'an$To'an$ association the relationship owner entit$ is the one that is dictated b$ the ?mappedB$? option usuall$ copnfiured with the !1 of =0 JPA Mini Book www.javacodegeeks.com A'an$To'an$ annotation at the non>owner entit$ of the relation. If the ?mappedB$? option is not found in an$ of the related entities *2A will define both entities as the relationship owners. The ?mappedB$? option must point to the associated entit$Hs attribute name and not the associated entit$Hs name. %here is no such 4auto relationship5 4or a Bidirectional relationship to wor+ correctl$ it is necessar$ to do li+e below. &ers'n.setD'g(d'gs"; d'g.setGers'ns(&ers'ns"; *2A uses the *ava concept of class reference! a class must maintain a reference to another one if there will be a join between them. *2A will not create a relationship automaticall$6 to have the relationship in both sides it is needed to do li+e above. ,any%o,any +ith extra fields Imaine a 2erson entit$ that has a 'an$To'an$ relationship with the ,o entit$6 ever$ time that a do is adopted b$ a person the application should reister the adoption date. This value must be stored in the relationship and not an an attribute on person nor do. To handle this +ind of situationwe use the ?Associative Class? alias ?Associative (ntit$? approach. 5ith this approach it is possible to store e3tra data when the 'an$To'an$ relationship is created. The imae below shows how this entit$ can be mapped. !3 of =0 JPA Mini Book www.javacodegeeks.com To map this e3tra field! implement li+e the followin code. import java.util.List;
-- get and set 9 The code above is usin the AOneTo'an$ relationship with the mappedB$ option. &otice that there is no A'an$To'an$ relationship between the entities! but there is an entit$ 2erson,o that unite both entities. Below is the 2erson,o code. import java.util.Date;
import java$.&ersisten%e.*;
K#ntit0 K3dClass(Gers'nD'g3d.class" public class Gers'nD'g {
K1em&'ral(1em&'ral10&e.DH1#" private Date ad'&ti'nDate;
-- get and set 9 In the code above $ou can see the relationships between 2erson,o! ,o and 2erson! and an e3tra attribute to store the adoption date. There is an id class to store the relationship ids named ?2erson,oId?. import java.i'.SerialiQa+le;
public class Gers'nD'g3d implements SerialiQa+le {
private static final lon serialNersi'n?3D , =L;
private int &ers'n; private int d'g;
public int getGers'n(" { return &ers'n; 9 !$ of =0 JPA Mini Book www.javacodegeeks.com
public void setGers'n(int &ers'n" { this.&ers'n , &ers'n; 9
public int getD'g(" { return d'g; 9
public void setD'g(int d'g" { this.d'g , d'g; 9
K6verride public int hashC'de(" { return &ers'n ; d'g; 9
return false; 9 9 One thin to notice here is that person and do attributes must have the same name > ?person? and ?do? here > between the 2erson,oId and 2erson,o entities. It is how *2A wor+s. 'ore information about comple3 +e$s can be found at earlier sections of this document. *o+ the 'ascade functionality +or6s? *o+ should a de1eloper use the .rphanRemo1al? *andling the org.hi&ernate.%ransient.&/ectException It is ver$ common two or more entities to receive updates in the same transaction. 5hen editin a personHs data for e3ample! we could chane their name! address! ae! car color etc. These chanes should trier updates to three different entities. 2erson! Car and Address. The updates above could be done as shown in the code snippet below. %ar.setC'l'r(C'l'r..#D"; %ar.set6Cner(neCGers'n"; %ar.setS'undS0stem(neCS'und"; != of =0 JPA Mini Book www.javacodegeeks.com If the code below were to be e3ecuted the e3ception or.hibernate.TransientObject(3ception would be thrown. #ntit0Manager entit0Manager , -- get a valid entit0 manager
Car %ar , new Car("; %ar.set)ame(*Bla%k 1hunder*";
Hddress address , new Hddress("; address.set)ame(*Street H*";
entit0Manager.get1ransa%ti'n(".%'mmit("; entit0Manager.%l'se("; 5ith the (clipse;in+ *2A implementation the followin messae would be fired. "Caused %y* +ava,lan!,-lle!alStateE./e(tion* 0urin! syn/hroni1ation a ne2 o%+e/t 2as &ound throu!h a relationshi( that 2as not mar3ed /as/ade PERS-S4. 5hat means that an entit$ is transient) Or what a relationship not mar+ed with cascade persist is all about) *2A wor+s as a trac+er for ever$ entit$ that participates in a transaction. An entit$ that participates in a transaction is an entit$ that will be created! updated! deleted. *2A needs to +now where that entit$ came from and where it is oin to. 5hen a transaction is opened ever$ entit$ brouht from the database is "attached#. 5ith "attached# we mean that the entit$ is inside a transaction! bein monitored b$ *2A. An entit$ remains attached until the transaction is closed 7rules for *%( applications or transactions without (*B %tateful %ession Beans with 2ersistence %cope (3tended are different96 to be attached an entit$ needs to come from a database 7b$ quer$! entit$ manaer find method/9! or receive some contact inside the transaction 7mere! refresh9. &otice the code below. entit0Manager.get1ransa%ti'n(".+egin("; Car m0Car , entit0Manager.(ind(Car.class4 DD"; m0Car.setC'l'r(C'l'r..#D"; entit0Manager. get1ransa%ti'n(".%'mmit("; The transaction is opened! an update is made in the entit$ and the transaction is committed. It was not required to do an e3plicit update to the entit$! with the transaction committin all updates made to the entit$ will be persisted to the database. The updates made to the Car entit$ were persisted to the database because the entit$ is attached! an$ update to an attached entit$ will be persisted in the database after the transaction commits79 or a flush call is made. !8 of =0 JPA Mini Book www.javacodegeeks.com As shown In the code snippet above ?m$Car? entit$ was brouht from the database inside a transaction! thus *2A will have the ?m$Car? entit$ attached into that 2ersistence Conte3t. It is possible to define a 2ersistence Conte3t as a place where *2A will put all attached entities to that transaction! or as a bi ba. The imaes below show this concept. !( of =0 JPA Mini Book www.javacodegeeks.com &otice in the imae above that the Car entit$ is added to the 2ersistence Conte3t onl$ after a database quer$ is performed to retrieve it from the database. (ver$ update in the Car entit$ will be monitored b$ *2A. Once the transaction is finished 7or the flush command invo+ed9! *2A will persist this chanes to the database. The aforementioned problem occures when we update a relationship between two entities. Chec+ the code and the imae below. entit0Manager.get1ransa%ti'n(".+egin("; Gers'n neCGers'n , new Gers'n("; neCGers'n.set)ame(*Mar0*"; Car m0Car , entit0Manager.(ind(Car.class4 DD"; m0Car.set6Cner(neCGers'n"; entit0Manager. get1ransa%ti'n(".%'mmit("; The Car entit$ establishes a relationship with the 2erson entit$. The problem is that the 2erson entit$ is outside of the 2ersistence Conte3t! notice that the person entit$ was not brouht from the database nor was attached to the transaction. -pon commit *2A cannot reconi8e that 2erson is a new entit$! which does not e3ist in the database. (ven if the 2erson entit$ e3isted in the database! since it came from outside a transaction 7e.. a *%4 'anaedBean! %truts Action9 it will be considerate unmanaable in this 2ersistence Conte3t. An object outside the 2ersistence Conte3t is +nown as "detached#. This detached entit$ situation ma$ happen in an$ *2A operations. I&%(RT! -2,AT(! ,(;(T(/ To help in these situations *2A created the option Cascade. This option can be defined in the annotations. AOneToOne! AOneTo'an$ and A'an$To'an$. The enum java3.persistence.CascadeT$pe has all Cascade options available. !9 of =0 JPA Mini Book www.javacodegeeks.com Chec+ the cascade options below. CascadeType.DETACH CascadeType.MERGE CascadeType.PERSIST CascadeType.REFRESH CascadeType.REMOVE CascadeType.ALL The Cascade applies the behavior to repeat the action defined in the relationship. %ee the code below. import java$.&ersisten%e.*;
-- get and set 9 In the persistence code above it is defined that the AOneToOne 2erson relationship will have the Cascade.2(R%I%T action e3ecuted ever$ time the command entit$'anaer.persist7car9 is e3ecuted6 thus for ever$ persist action invo+ed in a Car entit$ *2A will invo+e persist in the 2erson relationship also. The Cascade advantae is that the propaation of an action is automatic! just need to confiure it in a relationship. Chec+ below the Cascade options. Type Action Triggered by CascadeType.DETACH When the entty s removed from the Persstence Context (t w cause the entty to be detached) ths acton w be refected n the reatonshp. Fnshed Persstence Context or by command: enttyManager.detach(), enttyManager.cear(). CascadeType.MERGE When an entty has any When the entty s updated and $0 of =0 JPA Mini Book www.javacodegeeks.com data updated ths acton w be refected n the reatonshp. the transacton fnshes or by command: enttyManager.merge(). CascadeType.PERSIST When a new entty s perssted n the database ths acton w be refected n the reatonshp. When a transacton fnshes or by command:enttyManager.perss t(). CascadeType.REFRESH When an entty has ts data synchronzed wth the database ths acton w be refected n the reatonshp. By command: enttyManager.refresh(). CascadeType.REMOVE When an entty s deeted from the database ths acton w be refected n the reatonshp. By command: enttyManager.remove(). CascadeType.ALL When any of the actons above s nvoked by the |PA or by command, ths acton w be refected n the reatonshp. By any command or acton descrbed above. Once the cascade is defined! the code below should run without error. entit0Manager.get1ransa%ti'n(".+egin("; Gers'n neCGers'n , new Gers'n("; neCGers'n.set)ame(*Mar0*"; Car m0Car , entit0Manager.(ind(Car.class4 DD"; m0Car.set6Cner(neCGers'n"; entit0Manager. get1ransa%ti'n(".%'mmit("; Observations about Cascade. A deveoper must be cautous when usng CascadeType.ALL n a reatonshp. When the entty s deeted ts reatonshp woud be deeted as we. In the sampe code above, f the cascade type n the Car entty was set to the ALL opton, when a Car entty was deeted from the database the Person entty woud be deeted aso. CascadeType.ALL (or ndvdua cascades) can cause ow performance n every acton trggered n the entty. If for exampe an entty has a ot of sts of referenced enttes a merge() acton nvoked on the specfc entty coud cause a sts to be merged too. car.setOwner(personFromDB) => f the "personFromDB" entty exsts n the DB but s detached $/ of =0 JPA Mini Book www.javacodegeeks.com for the persstence context, Cascade w not hep. When the command enttyManager.persst(car) s executed |PA w run the persst command for every reatonshp defned wth CascadeType.PERSIST (e.g. enttyManager.persst(person)). If the Person entty aready exsts n the database |PA w try to nsert the same record agan and an error message w be thrown. In ths case ony "attached" enttes can be used, the best way to do t s by usng the getReference() method that we present here n more deta. In order for *2A to trier the cascade it is necessar$ alwa$s to e3ecute the action in the entit$ that has the cascade option defined. Chec+ the code below. import java$.&ersisten%e.*;
-- get and set 9 The correct wa$ to trier the cascade in the entities above is. entit0Manager.&ersist(%ar"; $1 of =0 JPA Mini Book www.javacodegeeks.com *2A will search inside the Car entit$ if there is a Cascade option that should be triered. If the persist was e3ecuted li+e below the transient error messae would be thrown. entit0Manager.&ersist(&ers'n"; Remem%er* the /as/ade 2ill only %e tri!!ered %y 5PA 2hen the a/tion is e.e/uted in the entity that has the Cas/ade /on&i!ured in the sam(le a%ove the Car /lass de&ined the Cas/ade to Person6 only the Car /lass 2ill tri!!er the Cas/ade, .rphanRemo1al The OrphanRemoval option wor+s almost li+e the CascadeT$pe.R('OI(. The OrphanRemoval is usuall$ applied in cases where an entit$ just e3ists inside another entit$. Imaine a situation where an Address entit$ will onl$ e3ist inside a 2erson entit$. If a new 2erson entit$ is persisted to the database an Address entit$ will be created too. Conceptuall$ the Address entit$ is created onl$ when a new 2erson entit$ is created and when the 2erson entit$ is deleted the Address entit$ is deleted also! just li+e b$ usin the CascadeT$pe.R('OI( option. The OrphanRemoval has almost the same functionalit$ as the CascadeT$pe.R('OI(! but conceptuall$ it must be applied at class composition level. ;oo+ at the code below. import java$.&ersisten%e.*;
K#ntit0 public class Hddress {
$3 of =0 JPA Mini Book www.javacodegeeks.com K3d KMeneratedNalue private int id;
-- get and set 9 Imaine that a specific Address entit$ is assined to a specific 2erson entit$ and onl$ that 2erson entit$ has access to it. As stated above OrphanRemoval is almost li+e CascadeT$pe.R('OI(. The difference is that the dependent entit$ will be deleted from the database if the attribute is set to null as showin at the code snippet below. &ers'n.setHddress(null"; 5hen the 2erson entit$ ets updated in the database! the Address entit$ will be deleted from the database. The person.setAddress7null9 would cause the Address entit$ to be orphan. The OrphanRemoval option is onl$ available in the annotations. AOneToOne and AOneTo'an$. *o+ to delete an entity +ith relationships. 'larify +hich relationships are raising the exception 5hen an entit$ is deleted from the database a constraint error ma$ appear! somethin li+e."+ava,s$l,S78-nte!rityConstraint9iolationE./e(tion. This error miht happen if we tr$ to delete a 2erson entit$ that is related to a Car entit$ and the CascadeT$pe.R('OI( is not defined for the specific association 7see the last chapter about Cascade definition9. $! of =0 JPA Mini Book www.javacodegeeks.com In order to perform the removal of the 2erson entit$ we could do. CascadeType.REMOVE => Once the entty s deeted ts chd entty (Car) w be deeted too. Check the prevous secton to see how to do t. OrphanRemova => Can be apped but have a dfferent behavor than CascadeType.REMOVE. Check the ast chapter to see how to do t. Set the reatonshp to nu before excudng t: &ers'n.setCar(null"; entit0Manager.rem've(&ers'n"; -nfortunatel$ locatin the actual entit$ that is the cause of the specific e3ception is not straihtforward at all. 5hat can be done is catch the class name displa$ed in the error messae of the e3ception and o on from there. This solution is not accurate because the error messae is a %trin with a lon te3t containin the database table name. &evertheless this messae ma$ chane b$ each distinct *2A implementation! *,BC driver! local database lanuae etc. 'reating one Entity,anager7actory &y application 5hen controllin database transactions prorammaticall$ one (ntit$'anaer4actor$ per application is usuall$ used. This is the optimal approach since loadin an (ntit$'anaer4actor$ has a hih performance cost6 *2A will anal$8e the database! validate entities and perform several other tas+s when creatin a new (ntit$'anaer4actor$. Thus it is unviable to create a new (ntit$'anaer4actor$ per transaction. Below is a code that can be used. import java$.&ersisten%e.*;
public abstract class C'nne%ti'n5a%t'r0 { private C'nne%ti'n5a%t'r0(" { 9
public static #ntit0Manager get#ntit0Manager("{ if (entit0Manager5a%t'r0 ,, null"{ entit0Manager5a%t'r0 , Gersisten%e.%reate#ntit0Manager5a%t'r0(*M0Gersisten%e?nit*"; 9
return entit0Manager5a%t'r0.%reate#ntit0Manager("; 9 9 $$ of =0 JPA Mini Book www.javacodegeeks.com 2nderstanding ho+ the La8y-Eager option +or6s An entit$ ma$ have an attribute with a hue si8e 7e.. a lare file9 or a bi list of entities e. a person ma$ have several cars or a picture with FG1 'B of si8e. Chec+ the code below. import java$.&ersisten%e.*;
-- get and set 9 About the code above. Notce that the coecton s assgned a FetchType.LAZY opton. Notce that the mage Byte|| hugePcture s assgned a FetchType.LAZY opton aso. $= of =0 JPA Mini Book www.javacodegeeks.com 5hen a field is mar+ed with a la8$ fetch t$pe option it is implied that *2A should not load the specific attribute "naturall$#. 5hen the command entit$'anaer.find72erson.class! person_id9 is used to retrieve the specific person from the database the ?cars? list and the ?hue2icture? field will not be loaded. The amount of data returned from the database will be smaller. The advantae of this approach is that the quer$ has less performance impact and the data traffic over the networ+ is smaller. This data can be accessed when the relevant et methods of the 2erson entit$ are invo+ed. 5hen the command person.et:ue2icture79 is e3ecuted a new quer$ will be fired aainst the database searchin this information. (ver$ simple attribute will have the 4etchT$pe.(AB(R option enabled b$ default. To mar+ a simple attribute as ;AJK fetched just add the annotation ABasic with the ;a8$ option selected just li+e above. The relationship between entities has a default behavior too. Reatonshps fnsh wth "One" w be EAGERy fetched: @OneToOne and @ManyToOne. Reatonshps fnsh wth "Many" w be LAZYy fetched: @OneToMany and @ManyToMany. To chane the default behavior $ou should do li+e demonstrated above. 5hen we use the ;AJK behavior the e3ception ";a8$ Initiali8ation (3ception# ma$ happen. This error happens when the ;AJK attribute is accessed without an$ opened connection. Chec+ this post to see how to solve this problem. Four soutons to the LazyIntazatonExcepton. The problem with (AB(R fetch t$pe in all list=attributes is that the database quer$ ma$ increase a lot. 4or e3ample if ever$ 2erson entit$ has a list of thousant of actions los! imaine the cost to brin hundred or even thousants of 2erson entities from the databaseL A developer must be ver$ cautious when choosin which +ind of fetch strate$ will be used to ever$ attribute=relationship. *andling the 4cannot simultaneously fetch multiple &ags5 error This error happens when *2A retrieves an entit$ from the database and this entit$ has more than one list fields mar+ed for (AB(Rl$ fetchin. Chec+ the code below. import java.util.List;
$8 of =0 JPA Mini Book www.javacodegeeks.com import java$.&ersisten%e.*;
-- get and set 9 5hen a quer$ to et the 2erson entit$ above is fired the followin error messae is displa$ed. "java3.persistence.2ersistence(3ception. or.hibernate.:ibernate(3ception. cannot simultaneousl$ fetch multiple bas#! a list can be +nown as ba. This error happens because :ibernate 7the specific *2A implementation farmewor+ used for this e3ample9 tries to brin the same result amount for each list. If the enerated %<; returns @ lines for the ?do? entit$ list and one for the ?car? entit$ list! :ibernate will repeat the ?car? quer$ to ma+e the result equal. Chec+ the imaes below to understand what is happenin when the entit$'anaer.find72erson.class! person_id9 command is e3ecuted. $( of =0 JPA Mini Book www.javacodegeeks.com The problem arises when repeated results appear and brea+ the correct quer$ result. The red cells in the imae above are the repeated results. There are four solutions for this situation. To use |ava.ut.Set nstead of other coecton types => wth ths easy change the error can be avoded. To use EcpseLnk => t s a radca souton, but for |PA ony users that use ony |PA annotatons ths change w have mnma mpact. To use FetchType.LAZY nstead of EAGER => ths souton s a temporary souton, because f a query fetches data from two coectons ths error may occur agan. For exampe the foowng query coud trgger the error: "seect p from Person p |on fetch p.dogs d |on fetch p.cars c". Addtonay when usng ths approach the LazyIntazatonExcepton error may happen. To use @LazyCoecton or @IndexCoumn of the Hbernate mpementaton n the coecton => t s a very good dea to understand how the @IndexCoumn works and ts effects when used, ts behavor w change varyng to whch sde of the reatonshp t s added (the expanaton of ths annotaton s outsde the scope of ths mn book). $9 of =0 JPA Mini Book www.javacodegeeks.com ABOUT THE AUTHOR Hebert Coelho is a senior *ava ,evelopment! with M certifications and a published boo+ about *%4 7portuuese onl$9. 4ounder of the blo uai:ebert.com visited from more than FN1 different countries. ABOUT THE EDITOR Byron Kiourtzoglou is a master software enineer wor+in in the IT and Telecom domains. :e is an applications developer in a wide variet$ of applications=services. :e is currentl$ actin as the team leader and technical architect for a proprietar$ service creation and interation platform for both the IT and Telecom industries in addition to a in>house bi data real>time anal$tics solution. :e is alwa$s fascinated b$ %OA! middleware services and mobile development. B$ron is co>founder and (3ecutive (ditor at *ava Code Bee+s. =0 of =0
Modern Web Applications with Next.JS: Learn Advanced Techniques to Build and Deploy Modern, Scalable and Production Ready React Applications with Next.JS