2013-01-20 11 views
5

Potrzebuję pomocy przy następnym problemie, który wydaje się podobny do tego one. Jednak sugerowane rozwiązanie nie działa w moim przypadku. Mam klasę RoadDistance oznaczoną jako @Ebbable oraz klasę RoadMetricLoader, która jest również @Ebbableable i zawiera dwa atrybuty typu RoadDistante. Istnieje również klasa RoadConnection, która jest Entity i zawiera atrybut typu RoadmetricLoader. Nie jestem udanych w nadrzędnymi atrybuty (@AttributeOverride) o RoadMetricLoader dla RoadDistance klasy (nie dostać pola ROAD_ESTIMATED_DISTANCE_VALUE, ROAD_ESTIMATED_DISTANCE_UNIT_ID, ROAD_REAL_DISTANCE_VALUE i ROAD_REAL_DISTANCE_UNIT_ID w ROAD_CONNECTION tabeli)JPA 2.0: @AttributeOverrides i odziedziczone atrybuty nie radzą sobie dobrze ze sobą

Baza danych jest MySQL 5.2.21 oraz bibliotek używanych w JPA 2.0 są te z EclipseLink 2.4.1

Próbowałem różnych opcji, ale żaden z nich nie działa. Pokazuję wszystkie opcje w komentarzach bloków w kodzie, który widzisz poniżej. Po odkomentowaniu jednej opcji pozostałe osoby skomentują. Oto wynik, który otrzymuję w każdym przypadku:

OPCJA 1: Nie zwraca żadnego błędu, ale w tabeli ROAD_CONNECTION otrzymuję tylko dwie wartości: VALUE i UNIT_ID.

WARIANT 2: Taki sam wynik jak wariant 1.

WARIANT 3: To był mój pierwszy zakład (patrz: official documentation example 2, a już wskazano link powyżej), ale pojawia się następny błąd

Local Exception Stack: 
Exception [EclipseLink-30005] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException 
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: [email protected] 
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.EntityManagerSetupException 
Exception Description: Predeployment of PersistenceUnit [jamUnit] failed. 
Internal Exception: Exception [EclipseLink-7309] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.ValidationException 
Exception Description: The attribute named [estimatedRoadDistance.unit] from the embeddable class [class net.question.RoadMetricLoader] is not a valid mapping to use with an attribute override for the attribute [metricLoader] on class [class net.question.RoadConnection]. 
    at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:127) 
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:118) 
    at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source) 
    at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source) 
    (...) 

Wariant 4: Taki sam jak Wariant 1 i 2.

Wariant 5:

Local Exception Stack: 
Exception [EclipseLink-30005] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException 
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: [email protected] 
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.EntityManagerSetupException 
Exception Description: Predeployment of PersistenceUnit [jamUnit] failed. 
Internal Exception: Exception [EclipseLink-7309] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.ValidationException 
Exception Description: The attribute named [unit] from the embeddable class [class net.question.RoadDistance] is not a valid mapping to use with an attribute override for the attribute [estimatedRoadDistance] on class [class net.question.RoadMetricLoader]. 
    at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:127) 
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:118) 
    at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source) 
    at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source) 
    (...) 

@Entity 
@Table(name="UNIT") 
public class Unit { 

    private Long id; 
    private String name; 
    private String measureSystemCode; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO, generator="UNIT_SEQ_GENERATOR") 
    @SequenceGenerator(name="UNIT_SEQ_GENERATOR", sequenceName="UNIT_SEQ") 
    @Column(name = "ID") 
    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    @Column(name = "NAME", nullable = false) 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @Column(name = "MEASURE_SYSTEM_CODE", nullable = false) 
    public String getMeasureSystemCode() { 
     return measureSystemCode; 
    } 

    public void setMeasureSystemCode(String measureSystemCode) { 
     this.measureSystemCode = measureSystemCode; 
    } 

} 

@MappedSuperclass 
public abstract class Metric<V extends Comparable<V>> { 

    private V value; 
    private Unit unit; 

    @Column(name = "VALUE", nullable = false) 
    public V getValue() { 
     return value; 
    } 

    public void setValue(V value) { 
     this.value = value; 
    } 

    @ManyToOne 
    @JoinColumn(name = "UNIT_ID", nullable = false) 
    public Unit getUnit() { 
     return unit; 
    } 

    public void setUnit(Unit unit) { 
     this.unit = unit; 
    } 

} 

@MappedSuperclass 
public abstract class ScalarPhysicalMetric<M extends Number & Comparable<M>> 
extends Metric<M> { 

} 

@Embeddable 
public final class RoadDistance extends ScalarPhysicalMetric<Double> { 

} 

/* 
// -##----------- OPTION 4 ----------> 
@AttributeOverrides({ 
    @AttributeOverride(name = "estimatedRoadDistance.value", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_VALUE")), 
    @AttributeOverride(name = "estimatedRoadDistance.unit", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_UNIT_ID")), 
    @AttributeOverride(name = "realRoadDistance.value", column = @Column(name = "ROAD_REAL_DISTANCE_VALUE")), 
    @AttributeOverride(name = "realRoadDistance.unit", column = @Column(name = "ROAD_REAL_DISTANCE_UNIT_ID")) 
}) 
// <---------- OPTION 4 -----------##- 
*/ 
@Embeddable 
public final class RoadMetricLoader { 

    private RoadDistance estimatedRoadDistance; 
    private RoadDistance realRoadDistance; 

    @Embedded 
    /* 
    // -##----------- OPTION 5 ----------> 
    @AttributeOverrides({ 
     @AttributeOverride(name = "value", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_VALUE")), 
     @AttributeOverride(name = "unit", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_UNIT_ID")) 
    }) 
    // <---------- OPTION 5 -----------##- 
    */ 
    public RoadDistance getEstimatedRoadDistance() { 
     return estimatedRoadDistance; 
    } 

    public void setEstimatedRoadDistance(RoadDistance estimatedRoadDistance) { 
     this.estimatedRoadDistance = estimatedRoadDistance; 
    } 

    @Embedded 
    /* 
    // -##----------- OPTION 5 ----------> 
    @AttributeOverrides({ 
     @AttributeOverride(name = "value", column = @Column(name = "ROAD_REAL_DISTANCE_VALUE")), 
     @AttributeOverride(name = "unit", column = @Column(name = "ROAD_REAL_DISTANCE_UNIT_ID")) 
    }) 
    // <---------- OPTION 5 -----------##- 
    */ 
    public RoadDistance getRealRoadDistance() { 
     return realRoadDistance; 
    } 

    public void setRealRoadDistance(RoadDistance realRoadDistance) { 
     this.realRoadDistance = realRoadDistance; 
    } 

} 

// -##----------- OPTION 1 ----------> 
/* 
@AttributeOverrides({ 
    @AttributeOverride(name = "estimatedRoadDistance.value", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_VALUE")), 
    @AttributeOverride(name = "estimatedRoadDistance.unit", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_UNIT_ID")), 
    @AttributeOverride(name = "realRoadDistance.value", column = @Column(name = "ROAD_REAL_DISTANCE_VALUE")), 
    @AttributeOverride(name = "realRoadDistance.unit", column = @Column(name = "ROAD_REAL_DISTANCE_UNIT_ID")) 
}) 
// <---------- OPTION 1 -----------##- 
*/ 
/* 
// -##----------- OPTION 2 ----------> 
@AttributeOverrides({ 
    @AttributeOverride(name = "metricLoader.estimatedRoadDistance.value", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_VALUE")), 
    @AttributeOverride(name = "metricLoader.estimatedRoadDistance.unit", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_UNIT_ID")), 
    @AttributeOverride(name = "metricLoader.realRoadDistance.value", column = @Column(name = "ROAD_REAL_DISTANCE_VALUE")), 
    @AttributeOverride(name = "metricLoader.realRoadDistance.unit", column = @Column(name = "ROAD_REAL_DISTANCE_UNIT_ID")) 
}) 
// <---------- OPTION 2 -----------##- 
*/ 
@Entity 
@Table(name="ROAD_CONNECTION") 
public class RoadConnection { 

    private Long id; 
    private String pointA; 
    private String pointB; 
    private RoadMetricLoader metricLoader; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO, generator="ROAD_CONNECTION_SEQ_GENERATOR") 
    @SequenceGenerator(name="ROAD_CONNECTION_SEQ_GENERATOR", sequenceName="ROAD_CONNECTION_SEQ") 
    @Column(name = "ID") 
    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    @Column(name = "POINT_A", nullable = false) 
    public String getPointA() { 
     return pointA; 
    } 

    public void setPointA(String pointA) { 
     this.pointA = pointA; 
    } 

    @Column(name = "POINT_B", nullable = false) 
    public String getPointB() { 
     return pointB; 
    } 

    public void setPointB(String pointB) { 
     this.pointB = pointB; 
    } 

    /* 
    // -##----------- OPTION 3 ----------> 
    @AttributeOverrides({ 
     @AttributeOverride(name = "estimatedRoadDistance.value", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_VALUE")), 
     @AttributeOverride(name = "estimatedRoadDistance.unit", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_UNIT_ID")), 
     @AttributeOverride(name = "realRoadDistance.value", column = @Column(name = "ROAD_REAL_DISTANCE_VALUE")), 
     @AttributeOverride(name = "realRoadDistance.unit", column = @Column(name = "ROAD_REAL_DISTANCE_UNIT_ID")) 
    }) 
    // <---------- OPTION 3 -----------##- 
    */ 
    @Embedded 
    public RoadMetricLoader getMetricLoader() { 
     return metricLoader; 
    } 

    public void setMetricLoader(RoadMetricLoader metricLoader) { 
     this.metricLoader = metricLoader; 
    } 

} 

Odpowiedz

4

AttributeOverride są dla podstawowych przekształceń. To czego potrzebujesz to AssociationOverride: http://docs.oracle.com/javaee/6/api/javax/persistence/AssociationOverride.html

+0

Dziękuję bardzo za powtórkę. Próbowałem też, co mówisz, jako alternatywę dla OPCJI 3 (W tej samej lokalizacji nad getMetricLoader) - Rzeczywiście, próbowałem więcej opcji niż te, które wskazałem. Instancja deklarowania wszystkich atrybutów jako AttributeOverride I oznaczała "estimRoadDistance.unit" i "realRoadDistance.unit" jako AssociationOverride. W bazie danych otrzymałem tabelę road_connection z polami: ID, POINT_A, POINT_B, ROAD_ESTIMATED_DISTANCE_VALUE, ROAD_REAL_DISTANCE_UNIT_ID, UNIT_ID. Nie wiem, dlaczego niektóre pola są poprawne, a inne błędne. – GYLZ

+0

W google, jeśli wyszukujesz "nie jest prawidłowym mapowaniem do użycia z przesłonięciem atrybutu dla atrybutu" (uwzględnione cudzysłowy) - sprawdź błędy zgłaszane dla OPCJI 3 i 5 - otrzymujesz tylko kilka wpisów i nie jest to zbyt pomocne. – GYLZ

+0

Nadpisania są zwykle na odwzorowaniu w encji, więc opcja 3 jest jedyną, której należy użyć, z AssotiationOverride dla odwzorowań relacji. Powiedział, że nie jestem pewien, czy możliwe jest rozszerzenie klasy mappedsuper, ponieważ są one przeznaczone dla encji. Jeśli jest to wymagane przez specyfikację, może być konieczne wypełnienie błędu przez Eclipselink. – Chris

1

Zgodnie z sugestią @Chris należy użyć AssociatedOverride.Jeżeli zmienisz RoadMetricLoader następująco:

public final class RoadMetricLoader { 

    private RoadDistance estimatedRoadDistance; 
    private RoadDistance realRoadDistance; 

    @Embedded 
    @AttributeOverrides({ 
     @AttributeOverride(name = "value", column = @Column(name = "ROAD_ESTIMATED_DISTANCE_VALUE")) 
    }) 
    @AssociationOverrides({ 
     @AssociationOverride(name = "unit", joinColumns = @JoinColumn(name = "ROAD_ESTIMATED_DISTANCE_UNIT_ID")) 
    }) 
    public RoadDistance getEstimatedRoadDistance() { 
     return estimatedRoadDistance; 
    } 

    public void setEstimatedRoadDistance(RoadDistance estimatedRoadDistance) { 
     this.estimatedRoadDistance = estimatedRoadDistance; 
    } 

    @Embedded 
    @AttributeOverrides({ 
     @AttributeOverride(name = "value", column = @Column(name = "ROAD_REAL_DISTANCE_VALUE")) 
    }) 
    @AssociationOverrides({ 
     @AssociationOverride(name = "unit", joinColumns = @JoinColumn(name = "ROAD_REAL_DISTANCE_UNIT_ID")) 
    }) 
    public RoadDistance getRealRoadDistance() { 
     return realRoadDistance; 
    } 

    public void setRealRoadDistance(RoadDistance realRoadDistance) { 
     this.realRoadDistance = realRoadDistance; 
    } 

teraz tabela jest poprawnie utworzone w DB:

enter image description here

W tym przypadku, można uzyskać również pozbyć @AttributeOverrides i @AssociationOverrides jak tam jest tylko jednym elementem dla każdego.

Powiązane problemy