2014-06-30 20 views
10

Ho un problema strano durante il caricamento di alcuni oggetti. Sto utilizzando JPA 1, hibernate-core versione 3.3.0.SP1 e hibernate-EntityManager versione 3.4.0.GAEreditarietà JPA e Hibernate Edizione

Diciamo che ho queste entità JPA:

@Entity 
@Table(name = "SLC_ELE") 
@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorColumn(discriminatorType = DiscriminatorType.INTEGER, name = ElementoPrograma.C_ID_CTG_ELE) 
public class Element { 
... 
} 

@Entity 
@Table(name = "SLC_ELE_ONE") 
@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorValue(Categories.ID_CTG_ONE) 
public class ElementTypeOne extends Element { 
    ... 
} 

@Entity 
@Table(name = "SLC_ELE_TWO") 
@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorValue(Categories.ID_CTG_TWO) 
public class ElementTypeTwo extends Element { 
    ... 
} 

@Entity 
@Table(name = ThreeElementExample.TABLENAME) 
@AssociationOverrides({ 
    @AssociationOverride(name = JpaMany3ManyEntity.ASOCIATION_OVERRIDE_ONE, 
    joinColumns = 
    @JoinColumn(name = Element.C_ID_ELE)), 
    @AssociationOverride(name = JpaMany3ManyEntity.ASOCIATION_OVERRIDE_TWO, 
    joinColumns = 
    @JoinColumn(name = OneEntity.C_ID_TWO)), 
    @AssociationOverride(name = JpaMany3ManyEntity.ASOCIATION_OVERRIDE_THREE, 
    joinColumns = 
    @JoinColumn(name = AnotherEntity.C_ID_THREE))}) 
public class ThreeElementExample extends JpaMany3ManyEntity<Element, OneEntity, AnotherEntity> { 
... 
} 

la cosa è, Mi piacerebbe ottenere sempre le sottoclassi (ovvero ElementTypeOne, ElementTypeTwo invece degli elementi) quando carico una collezione di queste entità. Il problema è che il molti a molti relazione sempre ottenere l'elemento (il padre invece i bambini)

Diciamo che ho un'entità A contenente un colection di elementi:

@Fetch(FetchMode.JOIN) 
@OneToMany(cascade = CascadeType.ALL, mappedBy = "idEle") 
private Collection<Element> elementCollection; 

E se ho la collezione, tutto funziona bene (ottengo le sottoclassi come previsto).

Il problema nasce quando ho un altro soggetto B con una collezione del JpaMany3ManyEntity (si noti che lo stesso elemento soggetto è coinvolto)

@OneToMany(cascade = CascadeType.ALL, mappedBy = JpaMany3ManyEntity.ASOCIATION_OVERRIDE_ONE, fetch = FetchType.LAZY) 
private Collection<ThreeElementExample> threeElementExampleCollection; 

Se io giro della threeElementExampleCollection dalla classe B, prima di cercare di ottenere l'elementoCollection dalla classe A, quando carico gli oggetti dall'elementoCollection Ottengo solo gli oggetti superclasse (Element) invece dei bambini.

Immagino che, per qualsiasi motivo, la relazione molti a molti ottenga sempre gli oggetti Element (padre) e li salva nella cache di ibernazione, ma ho bisogno di evitare questo comportamento.

Qualche idea o workarround? Qualsiasi tipo di aiuto sarebbe molto apprezzato.

Grazie in anticipo.

EDIT: il molti a molti classe:

@SuppressWarnings("serial") 
@MappedSuperclass 
@AssociationOverrides({ 
@AssociationOverride(name = JpaMany3ManyEntity.ASOCIATION_OVERRIDE_ONE, 
joinColumns = 
@JoinColumn(name = "changeMeWhenExtends")), 
@AssociationOverride(name = JpaMany3ManyEntity.ASOCIATION_OVERRIDE_TWO, 
joinColumns = 
@JoinColumn(name = "changeMeWhenExtends")), 
@AssociationOverride(name = JpaMany3ManyEntity.ASOCIATION_OVERRIDE_THREE, 
joinColumns = 
@JoinColumn(name = "changeMeWhenExtends"))}) 
public abstract class JpaMany3ManyEntity<A extends JpaBaseEntity, B extends JpaBaseEntity, C extends JpaBaseEntity> extends JpaBaseEntity { 

public static final String ID_ATTNAME = "id"; 

public static final String ASOCIATION_OVERRIDE_ONE = JpaMany3ManyEntity.ID_ATTNAME + "." + JpaMany3ManyId.ID_ONE_ATTNAME; 

public static final String ASOCIATION_OVERRIDE_TWO = JpaMany3ManyEntity.ID_ATTNAME + "." + JpaMany3ManyId.ID_TWO_ATTNAME; 

public static final String ASOCIATION_OVERRIDE_THREE = JpaMany3ManyEntity.ID_ATTNAME + "." + JpaMany3ManyId.ID_THREE_ATTNAME; 

... 
} 
+1

Ti dispiacerebbe aggiungere la definizione di 'JpaMany3ManyEntity' per completezza? –

+0

Nessun problema, ma sono abbastanza sicuro che non si tratti del problema. Ad ogni modo, la domanda è già stata modificata. – elcadro

risposta

3

Ecco un workarround che lavora per me: Deproxy le entità.

Pur avendo un proxy padre dell'entità (jpa.inheritance.issue.Element _ $$ _ javassist_1) se lo si deproxy, si otterranno le entità reali (figli).

Diciamo che si desidera eseguire il loop della raccolta di elementi (figli) dall'entità A e fare qualcosa con loro.

Qualcosa di simile:

public void loopDeproxyElements(List<Element> yourElementsCollection){ 
    for(Element p : yourElementsCollection){ 
     if(p instanceof HibernateProxy){ 
     Element child = (Element) ((HibernateProxy) p).getHibernateLazyInitializer() 
        .getImplementation(); 

     if (child instanceof ElementTypeOne){ 

     //You can cast your object or do whatever you want, knowing for sure that's a child element) 

      ElementTypeOne myRealElement = (ElementTypeOne) child; 
      ... 
      } else { 
      //It should be ElementTypeTwo (if u never create parent entities) 
      ... 
     } 
    }   
    } 
) 

Sarà sempre ottenere gli elementi di bambini come mi aspettavo.

+0

Puoi aggiungere codice di esempio su come lo usi effettivamente? –

+0

Questo è in realtà un esempio, basato sulle classi definite nella domanda, in cui si stanno ottenendo i valori da una raccolta lenta, ma si stanno depurando i valori, ottenendo sempre il tipo reale dell'entità. Il significato p è un elemento della collezione. – elcadro

+0

Da dove viene "p"? –

0

Provare con la proprietà hibernate.default_batch_fetch_size. Di default è impostato su 1. Questo caricherà solo la prima entità dalla tua collezione. Aumentare la dimensione della collezione potrebbe essere d'aiuto.

Problemi correlati