2013-03-28 17 views
9

Ich habe eine Tabelle mit Kundendaten in einer Oracle-Datenbank. Hier ist eine vereinfachte Definition:JPA Composite-Primärschlüssel mit Nullwert

CUSTOMER (CUSTOMER_ID NUMBER NOT NULL, 
      SOURCE_SYSTEM VARCHAR2(30), 
      FULL_NAME VARCHAR2(360), 
      PHONE_NUMBER VARCHAR2(240) 
     ) 

Der Primärschlüssel für diese Tabelle ist (CUSTOMER_ID, SOURCE_SYSTEM). Die Tabelle enthält zahlreiche Zeilen, für die SOURCE_SYSTEM null ist. Auf Datenbankebene gibt es kein Problem, aber wenn ich versuche, eine dieser Zeilen über JPA Entity zuzugreifen, verursacht es eine Reihe von Fragen:

1: em.find() Mit einer Reihe mit einem Null holen SOURCE_SYSTEM immer zu eine Null wird zurückgegeben.

2: Verwenden em.merge(), um eine Zeile mit einem Null SOURCE_SYSTEM aufzustellende, wenn der Datensatz in der Tabelle nicht vorhanden ist, aber nachfolgende Aktualisierungen fehlschlägt, da die Zusammenführung ALWAYS zu einem Insert führt ausgeführt wird.

3: em.createQuery() Verwendung explizit mit einem Null für eine Zeile zur Abfrage verursacht die folgende Ausnahme:

Exception [EclipseLink-6044] (Eclipse Persistence Services - 2.3.1.v20111018-r10243): 
    org.eclipse.persistence.exceptions.QueryException 
Exception Description: The primary key read from the row [ArrayRecord(
CUSTOMER.CUSTOMER_ID => 1 
CUSTOMER.FULL_NAME => GUY PERSON 
CUSTOMER.PHONE_NUMBER => 555-555-1234 
CUSTOMER.SOURCE_SYSTEM => null)] during the execution of the query was detected to be null. 
    Primary keys must not contain null. 
Query: ReadAllQuery(referenceClass=Customer sql="SELECT CUSTOMER_ID, FULL_NAME, PHONE_NUMBER, SOURCE_SYSTEM FROM CUSTOMER WHERE ((CUSTOMER_ID = ?) AND (SOURCE_SYSTEM IS NULL))") 

Leider „Primärschlüssel darf nicht null enthält“ scheint ziemlich endgültig. Ich konnte nicht zu viele Informationen zu Problemumgehungen für diesen Fehler finden, wodurch es scheint, als gäbe es keine Lösung.

DIE FRAGE: Ich würde gerne wissen, ob jemand eine Java-Code-basierte Lösung hat, die nicht mit Änderungen an der Datenbank zu machen. Meine aktuelle Problemumgehung ist, ROW_ID als @Id der Tabelle zu verwenden, aber das bedeutet, dass ich em.merge() oder em.find() nicht mehr verwenden kann.

Hier sind meine Java-Klassen:

Customer.java:

@Entity 
@Table(name = "CUSTOMER") 
public class Customer implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @EmbeddedId 
    private Customer_Id key; 

    @Column(name = "CUSTOMER_ID", nullable = false, insertable = false, updatable = false) 
    private Long customerId; 
    @Column(name = "SOURCE_SYSTEM", length = 30, insertable = false, updatable = false) 
    private String sourceSystem; 

    @Column(name = "FULL_NAME", length = 360) 
    private String fullName; 
    @Column(name = "PHONE_NUMBER", length = 240) 
    private String phoneNumber; 

    //Setters, Getters, etc 
    ... 
} 

Customer_Id.java

@Embeddable 
public class Customer_Id implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Column(name = "CUSTOMER_ID", nullable = false) 
    private Long customerId; 
    @Column(name = "SOURCE_SYSTEM", length = 30) 
    private String sourceSystem; 

    //Setters, Getters, etc 
    ... 
} 
+0

Warum verwenden Sie null für customer_id? Es sieht aus wie etwas, das Sequenzierung verwenden sollte, und wenn es nicht null ist, sollte das Feld source_system null sein. Sie können versuchen, die zu verwendende Validierung wie hier beschrieben zu spezifizieren http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_primarykey.htm, aber ich bin mir nicht sicher, warum das, was Sie haben, nicht funktionieren würde. Sie ordnen das customer_id-Feld zweimal zu, stellen Sie also sicher, dass Sie beide korrekt setzen – Chris

+0

Aktivieren Sie auch die Anmeldung, um festzustellen, ob Probleme mit Ihren Zuordnungen oder der generierten SQL-Datei auftreten. Abfragen für Nullfelder müssen in der Regel ein wenig anders sein, was möglicherweise seit der Überprüfung durch PK nicht mehr auftritt. http: //wiki.eclipse.org/EclipseLink/Beispiele/JPA/Logging beschreibt Eclipselink Logging – Chris

+0

'CUSTOMER_ID' wird nie Null sein, und ist markiert als 'Nullable = false' in der Klasse sowie' NOT NULL' in der Datenbank, obwohl es nicht darauf basiert eine Sequenz. Es ist sehr wahrscheinlich, dass das sql für 'em.find()' mit 'SOURCE_SYSTEM = ''' anstelle von 'SOURCE_SYSTEM IS NULL' generiert wird, weshalb der Datensatz nicht korrekt zurückgegeben wird. –

Antwort

0

Primärschlüssel kann nicht null enthalten (in JPA oder in Datenbanken). Verwenden Sie einen anderen Wert wie "" oder "".

Ist die customer_id eindeutig? Wenn ja, dann entferne einfach das sourceSystem von der ID.

Andernfalls könnten Sie versuchen, einen Fehler zu protokollieren, um Unterstützung für Null-IDs zu haben.

+0

'CUSTOMER_ID' ist nicht einzigartig, und ich Änderungen an der Tabelle können nicht vorgenommen werden, da sie bereits von anderen Anwendungen verwendet werden. Unglücklicherweise betrachtet [Oracle die leere Zeichenfolge als Nullwert] (http://www.techonthenet.com/oracle/questions/empty_null.php), und ich kann die vorhandenen Nullwerte in der Tabelle nicht ändern meine eigenen Bedürfnisse, da es sich auf andere Anwendungen auswirken würde, die derzeit eine Null in 'SOURCE_SYSTEM' erwarten. –