2016-04-09 10 views
1

meine Superklasse ist:JPA: in JOINED Vererbung Feld von Kind-Klasse holt

@Entity 
@Table(name = "TEST_VEHICLE") 
@ChangesListener 
@AttributeOverride(name = "id", column = @Column(name = "VEHICLE_ID")) 
@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorColumn(name = "VEHICLE_TYPE_ID", discriminatorType = DiscriminatorType.INTEGER) 
public abstract class Vehicle extends ParentEntity { 
    @Column(name = "MAX_SPEED", nullable = false) 
    private Integer maxSpeed; 

    public Integer getMaxSpeed() { 
     return maxSpeed; 
    } 

    public void setMaxSpeed(Integer maxSpeed) { 
     this.maxSpeed = maxSpeed; 
    } 
} 

und Unterklasse ist:

@Entity 
@Table(name = "TEST_BUS") 
@DiscriminatorValue("2") 
public class Bus extends Vehicle { 
    @Column(name = "PASSENGER_NUMBER", nullable = false) 
    private Short passengerNumber; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "FOO_OF_VEHICLE") 
    private Foo foo; 

    public Short getPassengerNumber() { 
     return passengerNumber; 
    } 

    public void setPassengerNumber(Short passengerNumber) { 
     this.passengerNumber = passengerNumber; 
    } 

    public Foo getFoo() { 
     return foo; 
    } 

    public void setFoo(Foo foo) { 
     this.foo = foo; 
    } 
} 

holt mit den foo auf Root<Vehicle> in Kriterien:

root.fetch("foo", JoinType.LEFT); 

verursacht diesen Fehler:

java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [foo] on this ManagedType ... 

Wie kann ich Felder von Unterklassen abrufen?

Update:

Behandlung mit löst nicht mein Problem:

Root<Bus> busRoot = builder.treat(root, Bus.class); 
busRoot.fetch("foo", JoinType.INNER); 

Ich erhalte keine Fehler aber foo holen noch nicht. generierten SQL ist:

SELECT vehicle0_.VEHICLE_ID AS VEHICLE_2_72_, 
    vehicle0_.ATTACHMENT_COUNT AS ATTACHME3_72_, 
    vehicle0_.COMMENTS   AS COMMENTS4_72_, 
    vehicle0_.CREATE_TIMESTAMP AS CREATE_T5_72_, 
    vehicle0_.CREATOR_USER_ID AS CREATOR_8_72_, 
    vehicle0_.MODIFIER_USER_ID AS MODIFIER9_72_, 
    vehicle0_.UPDATE_TIMESTAMP AS UPDATE_T6_72_, 
    vehicle0_.MAX_SPEED   AS MAX_SPEE7_72_, 
    vehicle0_1_.FOO_OF_VEHICLE AS FOO_OF_V3_70_, 
    vehicle0_1_.PASSENGER_NUMBER AS PASSENGE1_70_, 
    vehicle0_2_.ENGINE_TYPE  AS ENGINE_T1_71_, 
    vehicle0_.VEHICLE_TYPE_ID AS VEHICLE_1_72_ 
FROM TEST_VEHICLE vehicle0_ 
LEFT OUTER JOIN TEST_BUS vehicle0_1_ 
ON vehicle0_.VEHICLE_ID=vehicle0_1_.VEHICLE_ID 
LEFT OUTER JOIN TEST_CAR vehicle0_2_ 
ON vehicle0_.VEHICLE_ID =vehicle0_2_.VEHICLE_ID 
WHERE vehicle0_.VEHICLE_ID=105 
+0

Ein Fahrzeug ist nicht unbedingt ein Bus; Grundpolymorphismus. Cast things (treat) wenn der Zugriff auf Subclass-Felder gewünscht wird, genau wie bei Basic Java –

+0

Hier ist ein Auszug aus der JPA-Spezifikation: 'Die Wurzelobjekte der Abfrage sind Entitäten, von denen die anderen Typen durch nav- ignation erreicht werden Das bedeutet entweder, dass Sie die 'foo' in die' Vehicle' Klasse verschieben oder die 'Bus' Klasse zur Wurzel der Abfrage machen. – ujulu

+0

@NeilStockton ja. absolut. aber ich will Foo Feld holen, wenn es Bus ist. wie: 'root.fetch (" bus ", JoinType.LEFT) .fetch (" foo ", JoinType.LEFT);' aber diese Lösung funktioniert auch nicht. –

Antwort

0

Dieses Problem mithilfe von Meta-Modell gelöst werden können.

public abstract class Bus_ extends com.rh.cores.architecture.tests.models.Vehicle_ { 

    public static volatile SingularAttribute<Bus, Foo> foo; 
    public static volatile SingularAttribute<Bus, Short> passengerNumber; 
} 

bedeutet dies:

root.fetch(Bus_.foo, JoinType.LEFT); 

aber da JPA ist wie diese Signatur in holen:

<Y> Fetch<X, Y> fetch(SingularAttribute<? super X, Y> attribute, JoinType jt); 

oben Code Ursachen Fehler kompilieren! mit Code wie folgt zu ändern:

SingularAttribute attribute = Bus_.foo; 
root.fetch(attribute, JoinType.LEFT); 

wir Bypass Generika SingularAttribute<? super X, Y> in JPA-Standard überprüfen können, während Hibernate nur machen!