2014-06-30 18 views
10

Ich habe ein seltsames Problem beim Laden einiger Objekte. Ich bin mit 1 JPA, Hibernate-Core-Version 3.3.0.SP1 und Hibernate-EntityManager Version 3.4.0.GAVererbung JPA und Hibernate Problem

Lassen Sie uns sagen, dass ich diese JPA-Entitäten haben:

@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> { 
... 
} 

Die Sache ist, Ich möchte immer die Unterklassen erhalten (dh ElementTypeOne, ElementTypeTwo anstelle der Elemente), wenn ich eine Sammlung dieser Elemente lade. Das Problem ist, dass die viele zu viele Beziehung immer das Element erhalten (der Vater stattdessen die Kinder)

Sagen wir, ich habe eine Entität A ein colection der Elemente enthält:

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

Und wenn ich die Sammlung, alles funktioniert gut (ich bekomme die Unterklassen wie erwartet).

Das Problem kommt, wenn ich ein anderes Unternehmen B mit einer Sammlung der JpaMany3ManyEntity haben (beachten Sie, dass die gleiche Einheit Element beteiligt ist)

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

Wenn ich Schleife die threeElementExampleCollection von Klasse B, bevor ich versuche, zu erhalten die elementCollection aus der Klasse A, wenn ich die Objekte aus der elementCollection laden, bekomme ich nur die Oberklasse (Element) -Objekte statt der Kinder.

Ich vermute, dass die Beziehung viele zu viele immer die Element-Objekte (Vater) erhält und speichert sie im Ruhezustand-Cache, aber ich muss dieses Verhalten vermeiden.

Irgendwelche Ideen oder Workaround? Jede Art von Hilfe würde wirklich geschätzt werden.

Vielen Dank im Voraus.

EDIT: die viele zu viele Klasse:

@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

Würde es Ihnen etwas ausmachen, die Definition von 'JpaMany3ManyEntity' der Vollständigkeit halber hinzuzufügen? –

+0

Kein Problem, aber ich bin mir ziemlich sicher, dass das nicht das Problem ist. Wie auch immer, die Frage ist bereits bearbeitet. – elcadro

Antwort

3

Hier ist ein workarround, die mir funktioniert: Deproxy die Entitäten.

Sogar mit einem übergeordneten Proxy der Entität (jpa.inheritance.issue.Element _ $$ _ javassist_1), wenn Sie es deproxy, erhalten Sie die realen Entitäten (Kinder).

Nehmen wir an, Sie möchten Ihre (untergeordneten) Elemente-Sammlung von der Entität A aus loopen und etwas damit machen.

Etwas wie:

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) 
      ... 
     } 
    }   
    } 
) 

Es wird immer die Elemente Kinder bekommen, wie ich es erwartet hatte.

+0

Könnten Sie Beispielcode hinzufügen, wie Sie das tatsächlich verwenden? –

+0

Dies ist ein Beispiel, basierend auf den in der Frage definierten Klassen, wo Sie die Werte von einer faulen Sammlung erhalten, aber die Werte deproxieren, wobei immer der reale Typ der Entität erhalten wird. Bedeutung p ist ein Element aus der Sammlung. – elcadro

+0

Woher kommt "p"? –

0

Versuchen Sie Experiment mit hibernate.default_batch_fetch_size Eigenschaft. Standardmäßig ist es auf 1 gesetzt. Dadurch wird nur das erste Objekt aus Ihrer Sammlung geladen. Das Erhöhen auf ~ Größe der Sammlung könnte helfen.