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
...
}
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
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
'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. –