Newsgroup: it.comp.java
Titolo: Hibernate: mappare interfacce

Scusate, ma se non ho capito male, mappare un'interfaccia con Hibernate
è uguale a mappare una classe.
Però, ciò implica che devo avere i getter e setter per tutti i campi
nell'interfaccia, e mentre nelle classi potevo usare protected per i
setter che non volevo fossero acceduti da fuori, con una interfaccia
devo avere ovviamente tutto pubblico. E non mi piace.
C'è qualche soluzione che ignoro?
-- 
Herbie


Herbie, posso dirti una cosa scherzosa davvero senza offese ?
Dalle domande che fai non si si e' ancora capito se sei un mezzo genio o un
mezzo ritardato :-)) , 
nel senso che ti infili in situazioni estreme, non si sa se per zelo o perche'
te le cerchi inutilmente :
i Pojo/Entity NORMALMENTE non necessitano di interfacce, anzi potrebbero quasi
essere scorrette da usare a mio avviso.
Ciauz 
-- 

Il 06/10/10 13.09, Herbie ha scritto:

io veramente non ho capito *niente* di cosa vuoi fare e quale sia il tuo 
problema.

Mi associo


 essere scorrette da usare a mio avviso.
Secondo me non si puo' dire che una interfaccia sia "scorretta", al
massimo potrebbe essere "inutile".
Comunque.
Spieghero' con l'esempio concreto: ho dei soggetti, che possono essere
di vario tipo, per esempio "PersonaFisica", "SocietaPerAzioni".
Quindi, mi ero creato una interfaccia ISoggetto, implementata dalle
classi concrete. A me pare corretto!
Poi erano sorti dei problemi con Hibernate, nel frattempo li ho risolti,
perche' in questo caso si opera come quando si estende una classe
astratta.
In particolare, ho usato il discriminator, con strategia tabella singola
per class hierarchy.
Tuttavia, se dichiaro un campo "nome" nell'interfaccia, in essa ci
devono essere un setter e un getter pubblico, mentre in origine avevo
definito solo il getter. Volevo evitare il setNome nell'interfaccia.
Ma da quanto ho capito, l'unico modo e' dichiarare le proprieta' nelle
singole classi, dentro <subclass>. Se le dichiari nell'interfaccia, e' in
effetti logico che voglia anche il setter. Pero' mi rovina un po' il
design
ecco il mio mapping attuale (solo una implementazione per ora -
PersonaFisica)
------
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd
">
<hibernate-mapping package="mioprogetto.domain">
<class name="ISoggetto" table="soggetto" >
    <id name="id" column="id">
        <generator class="native"/>
    </id>
 
	<discriminator />  
 
	<property name="nome" />
	<subclass name="PersonaFisica">
	</subclass>  
 
 
</class>
</hibernate-mapping>
----
per togliere il setNome da ISoggetto, devo spostare la property nome
dentro PersonaFisica, ma poi per ogni implementazione devo ridichiararla
-- 
Herbie

dentro PersonaFisica, ma poi per ogni implementazione devo ridichiararla
Prova a levare l'interfaccia e usare classi e fai le stesse identiche cose che
con l'interfaccia con meno fastidi
in particolare fai girare per l'applicazione sempre references alla classe
madre e solo dove serve casti alla figlia ( PersonaFisica )
ciao Nicola
-- 

 madre e solo dove serve casti alla figlia ( PersonaFisica )
E' chiaro che molto della OOP puo' essere realizzato senza le
interfacce.
Tuttavia, la tua soluzione magari va bene nel mio caso particolare, dove
l'interfaccia - almeno per ora - puo' essere sostituita da una classe
base astratta o meno, ma in generale il problema rimane.
Nel senso che non e' che le interfacce non servono, perche', per dire la
prima cosa che mi viene un mente, gli oggetti potrebbero essere creati
da un factory che come implementazione potrebbe usare qualsiasi cosa, e
quindi l'interfaccia sarebbe esattamente cio' che ci vuole. 
Mi pare che a te le interfacce non stiano così simpatiche, a me invece
proprio tanto :), perché consentono di esprimere un contratto a
prescindere dalla sua implementazione
-- 
Herbie

 classi concrete. A me pare corretto!
in realtà non lo è. il polimorfismo si applica ai comportamenti degli
oggetti, non alle loro proprietà. i metodi accessori (getter/setter)
anche se sono metodi rappresentano le proprietà dell'oggetto.
nel tuo intento probabilmente ti serve che "soggetto" sia una classe
astratta che rappresenta le proprietà comuni.



Dunque, non hai certo torto, ma la questione mi pare un po' più
complessa.
Devo dire, innanzitutto, che non ho fatto esattamente ciò che ho scritto
(e per fare un esempio ho scritto di fretta quanto sopra): in
particolare, ho creato una interfaccia ISoggetto, implementata da
SoggettoGenerico, che è esteso da SocietaPerAzioni (per ora
non ho ancora creato PersonaFisica, perché non ho altre proprietà da
farle gestire, sebbene nella realtà ci siano e prob.te ci saranno)
Quindi qualcosa di simile a quanto dici tu.
Per quanto riguarda l'interfaccia, forse sono andato in
"sovra-ingegnerizzazione", nel senso che è probabile che non mi serva.
Ma siccome la classe era una di quelle centrali nel mio modello, avevo
pensato, per sicurezza, di usarla. 
Supponiamo di avere PersonaFisica e SocietàPerAzioni che ereditano da
SoggettoGenerico.
SocietàPerAzioni differisce effettivamente da
PersonaFisica perché SocietàPerAzioni può avere degli azionisti, mentre
SoggettoGenerico no. Non so se tu cataloghi ciò nelle proprietà, ma io lo
vedo anche come un comportamento (sebbene non lo sia in senso stretto
polimorfico). Quindi una soluzione potrebbe essere far implementare a
entrambi l'interfaccia ISoggetto e far implementare a SocietàPerAzioni
anche una interfaccia "IPartecipabile".
Il mio "Manuale di Java" di Gosling e company scrive peraltro a un certo
punto: "Ognuna delle classi principali di un'applicazione dovrebbe
essere implementazione di qualche interfaccia che "catturi" il contratto
della classe specifica".
Inoltre, alcuni portano a sostegno dell'uso delle interfacce in modo
esteso la creazione di mock objects o la dependency injection. Cose che,
effettivamente, non uso per ora nel mio progetto, ma a volte tendo a
tenermi un po' "largo".
Ho comunque un problema un po' grossino, che credo mi porterà a cambiare
quell'ipotetico design: creo questi oggetti (SoggettoGenerico e
SocietàPerAzioni) leggendo alcuni dati, da una sorgente dove non è
specificato se i soggetti sono di un tipo o dell'altro.
Quindi, nel momento in cui un soggetto s è indicato come azionista di
qualcuno, in un primo momento lo creo come SoggettoGenerico, perché non
so se è una persona o una società. Poi se vedo che qualcuno è azionista
di s, allora deduco che s è SocietàPerAzioni.  
Ma con gli oggetti, come faccio?
In un primo momento, trasformavo un oggetto da un tipo ad un altro, in
pratica ricreandolo col tipo corretto, copiandoci i dati del vecchio, ed
eliminando quest'ultimo.
Ma questa soluzione non mi piace per niente.
Al momento, per semplificare le cose, ho pensato di usare lo State
Pattern, e di variare così lo stato (PersonaFisica,
SoggettoNonIdentificato, SocietàPerAzioni) di un soggetto. Potrei quindi
avere Soggetto con un campo azionistiDelSoggetto e un getter relativo,
che darebbe UnsupportedOperationException se Soggetto non è una
SocietàPerAzioni, e gli azionisti negli altri casi (be', facendola più
semplice potrei semplicemente riportare null per gli azionisti quando
non presenti, sebbene a una persona fisica non dovrebbe neanche essere
permesso chiedere se ha azionisti). 
Si valutano eventuali proposte :-)
-- 
Herbie

 Ma con gli oggetti, come faccio?
Ho discusso la questione anche altrove. Cioè che avevo esattamente io,
cioè un oggetto capace di cambiare interfaccia, sarebbe fattibile
tramite dynamic proxy. 
Non so se userò quello, la soluzione più semplice è effettivamente
creare un nuovo oggetto copiandoci i dati del vecchio, però la soluzione
dynamic proxy è di una potenza mostruosa :-), anche se però ci va di
mezzo la reflection e magari non è così efficiente (ma non ho proprio
provato)
-- 
Herbie

 eliminando quest'ultimo.
[...]
Ovviamente non esiste mai una sola soluzione, ma ce ne sono N-mila.
Solo che di solito in questa rosa di possibili soluzioni ce n'e'
sempre qualcuna piu' facile delle altre, e nel tuo caso non e' certo
la copia dell'oggetto o l'uso dei dynamic proxies! Di solito, la
soluzione piu' complessa e' anche quella piu' sbagliata :)
- Soluzione 1 (la piu' semplice):
Dalla tua complicatissima base dati, leggi per prima cosa il
"discriminator" (la lista di azionisti nel tuo caso) e in base a
quello crea un oggetto oppure l'altro.
- Soluzione 2 (la piu' trendy):
Una factory mette a disposizione un bel metodo:
static Soggetto createSoggetto( ... );
dove al posto dei puntini ci sono tutti i parametri che ti servono per
creare un tipo di oggetto oppure l'altro. L'implementazione conterra'
un "if" sul tuo discriminator.
- Soluzione 3 (la piu' "ohhhhhhh"):
Se quello che per te distingue un oggetto da un altro e' solo la
presenza di azionisti, allora potrebbe non servirti distinguere tra un
tipo di oggetto e l'altro. Semplicemente alcuni oggetti Soggetto
avranno degli azionisti, altri non li avranno.
--
SoulSpirit

 avranno degli azionisti, altri non li avranno.
Beh, la mia descrizione era semplificata, quindi questo non basta, ma
senza dubbio sarebbe da mettere in atto, se possibile
-- 
Herbie