Po implementácii CMP enterprise beanu obvykle nasleduje definovanie deployment deskriptora. Preto sa budeme venovať jeho tvorbe z pohľadu Container Managed Persistence. Všetky uvedené príklady budú vzorové a typické, s ktorými sa môžete pri štúdiu stretnúť najčastejšie.

Abstraktná schéma perzistencie

Deployment deskriptor pre CMP entitu obsahuje definíciu jej perzistentných polí a vzťahov, ktorá sa označuje pojmom abstraktná schéma perzistencie. Informácie uložené v ejb-jar.xml deskriptore predstavujú logický pohľad na CMP entitu vrátane je vzťahov s okolím, avšak neobsahuje fyzické mapovanie na podkladovú databázu. Táto úloha spočíva na tom, ktorý vykonáva samotný deployment, a obvykle je nutné použiť špecifické O/RM nástroje. Schéma perzistencie identifikuje metódy, ktoré majú umožňovať prístup k perzistentným poliam a vzťahom (CMP a CMR) spravovaných EJB kontajnerom. Toto je zabezpečené použitím skupiny <cmp-field> a <cmr-field> elementov.

Každé virtuálne CMP pole vyskytujúce sa vo vašej entitnej triede by malo byť identifikované v schéme perzistencie ako <cmp-field> element. Napríklad ako v uvedenej ukážke:

<entity>
 <ejb-name>EnglishAuction</ejb-name>
 <local-home>interval.EnglishAuctionHome</local-home>
 <local>interval.EnglishAuction</local>
 <ejb-class>interval.EnglishAuctionCMPBean</ejb-class>
 <persistence-type>Container</persistence-type>
 <prim-key-class>java.lang.Integer</prim-key-class>
 <reentrant>False</reentrant>
 <cmp-version>2.x</cmp-version>
 <abstract-schema-name>EnglishAuction</abstract-schema-name>
 <cmp-field>
  <description>The primary key field</description>
  <field-name>idField</field-name>
 </cmp-field>
 <cmp-field>
  <field-name>nameField</field-name>
 </cmp-field>
 <cmp-field>
  <field-name>descriptionField</field-name>
 </cmp-field>
 
 <primkey-field>idField</primkey-field>
 
</entity>

Obsah elementu <abstract-schema-name> musí byť validný Java identifikátor a v rámci ostatných identických elementov musí byť unikátny. Ďalej si všimnite, že názvy CMP polí musia začínať malým písmenom. V ich prípade musí byť dodržaná štandardná JavaBeans menná konvencia, aby bolo možné spárovať jednotlivé CMP perzistentné polia s názvami abstraktných metód definovaných v entitnej triede. Napríklad CMP pole descriptionField musí mať definované v entitnej triede korešpondujúce metódy setDescriptionField a getDescriptionField.

Všimnite si, že v uvedenom príklade nikde nie je uvedené, ako sú jednotlivé polia mapované na databázu. Znamená to, že ejb-jar.xml je určený iba na identifikovanie perzistentných polí. Až špecifické nástroje používané pri deploymente a EJB kontajnerom definovaný deployment deskriptor sú použité na mapovanie abstraktnej schémy perzistencie na konkrétny dátový zdroj.

Relácie medzi entitami sú definované pomocou elementu <ejb-relation> v rámci časti <relationships> deployment deskriptora ejb-jar.xml. Nasledovný príklad to ilustruje.

Element <relationships> definujúci CMR vzťahy v deskriptore ejb-jar.xml:

<ejb-jar>
<enterprise-beans>
 <entity>
  <ejb-name>EnglishAuction</ejb-name>
  
 </entity>
 <entity>
  <ejb-name>AuctionBid</ejb-name>
  
 </entity>
 <entity>
  <ejb-name>Item</ejb-name>
  
 </entity>
 
</enterprise-beans>

<relationships>
 <ejb-relation>
  <ejb-relation-name>
   EnglishAuction-AuctionBid
  </ejb-relation-name>
  <ejb-relationship-role>
   <ejb-relationship-role-name>
    auction-has-bids
   </ejb-relationship-role-name>
   <multiplicity>one</multiplicity>
   <relationship-role-source>
    <ejb-name>EnglishAuction</ejb-name>
   </relationship-role-source>
   <cmr-field>
    <cmr-field-name>bids</cmr-field-name>
    <cmr-field-type>java.util.Collection</cmr-field-type>
   </cmr-field>
  </ejb-relationship-role>
  <ejb-relationship-role>
   <ejb-relationship-role-name>
    bid-belongs-to-auction
   </ejb-relationship-role-name>
   <multiplicity>many</multiplicity>
   <cascade-delete/>
   <relationship-role-source>
    <ejb-name>AuctionBid</ejb-name>
   </relationship-role-source>
   <cmr-field>
    <cmr-field-name>auction</cmr-field-name>
   </cmr-field>
  </ejb-relationship-role>
 </ejb-relation>
 
 <ejb-relation>
  <ejb-relation-name>
   EnglishAuction-Item
  </ejb-relation-name>
  <ejb-relationship-role>
   <ejb-relationship-role-name>
    auction-offers-item
   </ejb-relationship-role-name>
   <multiplicity>one</multiplicity>
   <relationship-role-source>
    <ejb-name>EnglishAuction</ejb-name>
   </relationship-role-source>
   <cmr-field>
    <cmr-field-name>item</cmr-field-name>
   </cmr-field>
  </ejb-relationship-role>
  <ejb-relationship-role>
   <ejb-relationship-role-name>
    item-is-offered-by-auction
   </ejb-relationship-role-name>
   <multiplicity>one</multiplicity>
   <relationship-role-source>
    <ejb-name>Item</ejb-name>
   </relationship-role-source>
  </ejb-relationship-role>
 </ejb-relation>

</relationships>

<assembly-descriptor>

</assembly-descriptor>

</ejb-jar>

Uvedený príklad definuje vzťah medzi aukciou a jednotlivými ponukami typu one-to-many a vzťah medzi aukciou a jej položkami typu one-to-one. Pre každý element <ejb-relation> môžete zadefinovať ľubovoľný unikátny element <ejb-relation-name>. Následne sa vyžaduje zadefinovanie elementu <ejb-relationship-role> pre každú stranu definovaného vzťahu. Aj pre tento element môžete zadefinovať ľubovoľný názov, ale musí byť unikátny v rámci súboru. Element <multiplicity> vyjadruje početnosť objektov entity, z ktorej opisovaný vzťah vychádza. V našom príklade je pre entitu EnglishAuction zadefinované, že vystupuje ako jedna vo vzťahu k viacerým entitám AuctionBid. Všimnite si, že v tomto vzťahu vystupuje aj uzavretý element <cascade-delete/>. Jeho úlohou je informovať EJB kontajner, že v prípade požiadavky na zmazanie objektu entity EnglishAuction treba zmazať aj všetky asociované objekty entity AuctionBid.

Element <relationship-role-source> identifikuje entitu vystupujúcu v definovanom vzťahu s použitím vnoreného elementu <ejb-name>. Skutočnosť, že je element <cmr-field> umiestnený až za elementom <relationship-role-source>, definuje smer tohto vzťahu. Napríklad v prípade druhého z nich je povedané, že položka aukcie (entita Item) nemôže vedieť, k akej aukcii je priradená, ale v opačnom smere to platí. Čiže jedná sa o jednosmerný vzťah v smere EnglishAuction -> Item.

V prípade aukcie a jednotlivých ponúk je vzťah obojsmerný, čo je zabezpečené pomocou elementov <cmr-field>, ktoré sa nachádzajú na oboch stranách tohto vzťahu. Podobne ako pri CMP poliach, aj pri elemente <cmr-field-name> musí ísť o validný Java identifikátor, začínajúci na malé písmená a odpovedajúci dvojici abstraktných get/set metód v triede beanu. V prípade vzťahov typu O2M a M2M musíte ešte určiť, či CMR pole bude používať objekty triedy java.util.Collection alebo java.util.Set prostredníctvom elementu <cmr-field-type>.

Implementácia finder a select metód

Vyhľadávacie finder metódy deklarované v home rozhraní enterprise beanu sa definujú v deployment deskriptore. V prípade CMP perzistencie nie je nutné zabezpečiť žiadnu implementáciu týchto metód z vašej strany, dokonca ani deklarovaním abstraktných metód. Vyhľadávacie metódy sa špecifikujú prostredníctvom EJB Query jazyka, čo je jazyk s podobnou syntaxou ako SQL.

Element <query> definujúci dotaz pre finder alebo select metódu.

<ejb-jar>
 <enterprise-beans>
  <entity>
   <ejb-name>EnglishAuction</ejb-name>
   …
   <query>
    <query-method>
     <method-name>findAllAuctions</method-name>
     <method-params/>
    </query-method>
    <ejb-ql>
     <![CDATA[ SELECT OBJECT(a) FROM EnglishAuction AS a]]>
    </ejb-ql>
   </query>
   <query>
    <query-method>
     <method-name>findNonPendingAuctions</method-name>
     <method-params/>
    </query-method>
    <ejb-ql>
     <![CDATA[ SELECT OBJECT(a) FROM EnglishAuction AS a WHERE a.statusField <> ‚Pending‘]]>
    </ejb-ql>
   </query>
   <query>
    <query-method>
     <method-name>ejbSelectAuctionedItems</method-name>
     <method-params/>
    </query-method>
    <ejb-ql>
     <![CDATA[ SELECT OBJECT(i) FROM EnglishAuction AS a, IN(a.item) i]]>
    </ejb-ql>
   </query>
  …
  </entity>
 …
 </enterprise-beans>

</ejb-jar>

Ako sme si už boli povedali, element <query-method> sa používa na identifikovanie finder metód deklarovaných v home rozhraní beanu. Ak máte nejakú vyhľadávaciu metódu deklarovanú v oboch home rozhraniach (remote aj local) súčasne pod rovnakým menom a s rovnakým zoznamom parametrov, potom kontajner môže automaticky implementovať obe metódy na základe jednej spoločnej deklarácie <query>. Obsah elementu <method-name> musí presne odpovedať názvu metódy v home rozhraní beanu a nie názvu metódy definovanej priamo v entitnej triede. Inými slovami, názov metódy musí začínať na find a nie na ejbFind. Element <ejb-ql> definuje dotaz, ktorý sa vykoná vždy, keď je zavolaná konkrétna vyhľadávacia metóda.

V prípade výberových select metód je použitá syntax takmer úplne rovnaká ako pri vyhľadávacích metódach – s tým rozdielom, že názov metódy definovaný v rámci elementu <method-name> musí presne odpovedať názvu metódy deklarovanej priamo v entitnej triede (ako abstraktná metóda). Čiže názov každej metódy musí začínať na ejbSelect.

Mapovanie abstraktnej schémy perzistencie na databázu

Keď príde čas na mapovanie schémy perzistencie na podkladovú databázu, prípadne iný dátový zdroj, začne byť celý proces vývoja aplikácie závislý na špecifických nástrojoch dodávaných s EJB kontajnerom, respektíve tretími stranami. Tieto nástroje obvykle vytvárajú proprietárne deployment deskriptory, ktoré sú následne použité spoločne s ejb-jar.xml. V nasledujúcom príklade si môžete prezrieť časť dvoch deployment deskriptorov použitých WebLogic serverom na nasadenie CMP entity beanu.

Žádný příspěvek v diskuzi

Odpovědět