Hibernate Associazioni polimorfiche Dott. Doria Mauro [email protected] [email protected] Associazioni polimorfiche Una delle caratteristiche fondamentali di un ORM framework è la capacità di supportare le associazioni polimorfiche e le query polimorfiche. Una associazione polimorfica è una associazione tra una classe concreta e un’altra entità la quale può essere: – – – Una superclasse Una classe astratta Una interfaccia (dipende da come è stata mappata la generalizzazione) 2 Gran parte del lavoro è stato effettuato mappando la generalizzazione tra le classi; il mapping delle associazioni polimorfiche è relativamente semplice. [email protected] Associazioni polimorfiche Vediamo un primo esempio: Un user possiede un sistema di pagamento; questio può essere di diverso tipo, ad esempio carta di credito o bonifico bancario. 1 3 NOTA: User ha due associazioni polimorfiche con BillingDetails Quando si costruisce un oggetto user, si assegna polimorficamente un oggetto di tipo BillingDetails. Nel rendere persistente l’oggetto user, Hibernate provvede a creare l’associazione tra i redcord user e il record corrispondente al BillingDetails scelto per l’user. [email protected] Associazioni polimorfiche singoli valori Iniziamo con il mappare all’associazione “default” Il mapping della classe User sarà: Superclasse interfaccia o classe astratta. Dipende dalle politiche di mapping della generalizzazione <many-to-one name="defaultBillingDetails” class="BillingDetails“ cascade=“all” column="DEFAULT_BILLING_DETAILS_ID"/> 4 Tenendo conto che la classe BillingDetails è stata mappata con le sue sottoclassi, non vi solo altre cose da fare. Di seguito, come rendere persistente un user: User unUser = new User("Alvaro", "Vitali"); CreditCard unaCc = new CreditCard("pippo", "10", 12,2009); unUser.setDefaultBillingDetails(cc); session.save(unUser); [email protected] Associazioni polimorfiche singoli valori Hibernate gestisce le associazioni polimorfiche allo scopo di allineare la logica del polimorfismo con quella del mapping con la base dati. Vediamo cosa significa questo con un esempio: //si recupera una istanza user dal DB User user = (User) session.get(User.class, userId); // si invoca il metodo pay() sull’istanza restituita BillingDetails bill = user.getDefaultBillingDetails(); bill.pay(); 5 Hibernate mappa l’oggetto user con il suo concreto tipo di pagamento sul DB Il metodo user.getDefaultBillingDetails() restituisce un oggetto concreto di tipo BillingDetails (CreditCard o BankAccount) ma viene assegnato al tipo generico BillingDetails. Invocando il metodo pay si attiva il polimorfismo java. [email protected] Associazioni polimorfiche lazy-loading Attenzione: Hibernate attiva il lazy-loading di default (lazy = true); questo comporta la possibile presenza di una classe proxy al posto della classe concreta di tipo BillingDetails. Quindi, il seguente codice potrebbe portare ad una BadCastException Instanza proxy User unUser = (User) session.get(User.class, userid); BillingDetails bd = unUser.getDefaultBillingDetails(); System.out.println( bd instanceof CreditCard ); // se stampa "false" CreditCard unaCc = (CreditCard) bd; // ClassCastException! In ogni caso, nella maggior parte dei casi, non c’è motivo di fare un cast alla classe specifica 6 [email protected] Associazioni polimorfiche collections polimorfiche Vediamo adesso l’associazione bidirezionale uno-a-molti tra User e BillingDetails. Aggiungiamo nel mapping della classe Billing Details: <many-to-one name="user" class="User" column="USER_ID"/> 7 Mentre per la classe User: <set name="billingDetails“ inverse="true"> <key column="USER_ID"/> <one-to-many class="BillingDetails"/> </set> [email protected] Associazioni polimorfiche collections polimorfiche Di seguito un utilizzo polimorfico dell’user: invocazione del metodo pay() su tutti gli oggetti di tipo BillingDetails di un user, qualunque siano le classi che concretizzano BillingDetails. User unUser = (User) session.get(User.class, userId); for( BillingDetails bd : unUser.getBillingDetails() ) { // si invoca il metodo pay() di BankAccount o di CreditCard bd.pay(totale); } 8 [email protected] Associazioni polimorfiche collections polimorfiche: mapping di tipo uno Sono previste delle operazioni aggiuntive per il mapping della generalizzazione fatta con le prime due strategie (normale e <unionsubcalss>) Primo caso, mapping di tipo uno (normale) : – 9 non abbiamo necessariamente una tabella per la classe BillingDetails e quindi dobbiamo aggiungere una chiave esterna a mano nelle tabelle concrete. Se la superclasse BillingDetails è concreta, nel suo mapping dobbiamo aggiungere una chiave esterna verso user. <many-to-one name="user" column="USER_ID" class="User"/> [email protected] Associazioni polimorfiche collections polimorfiche: mapping di tipo uno 10 Se la superclasse BillingDetails è astratta o è una interfaccia, non abbiamo una tabella in corrispondenza di BillingDetails. In questo caso è necessaria una configurazione aggiuntiva per il mapping di User: <any name="defaultBillingDetails" id-type="long" meta-type="string"> <meta-value value="CREDIT_CARD" class="CreditCard"/> <meta-value value="BANK_ACCOUNT“ class="BankAccount"/> <column name="DEFAULT_BILLING_DETAILS_TYPE"/> <column name="DEFAULT_BILLING_DETAILS_ID"/> </any> [email protected] Associazioni polimorfiche collections polimorfiche: mapping di tipo due Secondo caso, mapping di tipo due (union-subclass) : – non abbiamo necessariamente una tabella per la classe BillingDetails (dipende dall’attributo abstract); in ogni caso dobbiamo aggiungere una chiave esterna a mano nelle tabelle concrete. Indipendentemente dal valore di abstract, viene aggiunta una colonna nuova in ogni tabella concreta 11 <class name="BillingDetails" abstract="true"> <id name="id" column="BILLING_DETAILS_ID" .../> <property .../> <many-to-one name="user“ column="USER_ID“ class="User"/> <union-subclass name="CreditCard" table="CREDIT_CARD"> <property .../> </union-subclass> <union-subclass name="BankAccount" table="BANK_ACCOUNT"> <property .../> </union-subclass> </class> [email protected] Domande? Collection polimorfiche <any> Associazioni polimorfiche generalizzazione polimorfismo proxy <union-subclass> 12 Polimorfismo
© Copyright 2025 ExpyDoc