我有一個包含oracle數據庫中的客戶數據的表。下面是一個簡化的定義:具有空值的JPA複合主鍵
CUSTOMER (CUSTOMER_ID NUMBER NOT NULL,
SOURCE_SYSTEM VARCHAR2(30),
FULL_NAME VARCHAR2(360),
PHONE_NUMBER VARCHAR2(240)
)
此表的主鍵是(CUSTOMER_ID, SOURCE_SYSTEM)
。
該表有許多行,其中SOURCE_SYSTEM
爲空。在數據庫級別,沒有問題,但是當我嘗試訪問任何通過JPA實體這些行的,它會導致一些問題:
1:使用em.find()
用空SOURCE_SYSTEM
總是導致中讀取行返回null。
2:使用em.merge()
到UPSERT一排空SOURCE_SYSTEM
成功,如果記錄不存在於表中,但在後續的更新失敗,因爲合併總是導致插入正在運行。
3:使用em.createQuery()
明確查詢與空行導致以下異常:
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))")
不幸的是,「主鍵不能包含空」似乎相當決賽。我無法找到有關此錯誤的解決方法的太多信息,這看起來好像沒有解決方案。
問題:我想知道如果任何人有任何基於Java代碼的解決方案不涉及更改數據庫。我目前的解決方法是使用ROW_ID
作爲表中的@Id
,但這意味着我不能再使用em.merge()
或em.find()
。
這裏是我的Java類:
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
...
}
你爲什麼使用null作爲customer_id?它看起來像應該使用排序的東西,如果它不爲空,應該允許source_system字段爲空。您可以嘗試指定要使用的驗證,如http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_primarykey.htm中所述,但我不確定爲什麼您的操作不起作用。您正在映射customer_id字段兩次,因此請確保您正確地設置了這兩個字段。 – Chris
還打開日誌記錄以查看映射或生成的SQL是否存在問題。對空字段的查詢通常必須略有不同,這可能不會發生,因爲它的pk檢查。 HTTP://wiki.eclipse。org/EclipseLink/Examples/JPA/Logging描述了Eclipselink日誌記錄 – Chris
'CUSTOMER_ID'永遠不會爲空,並且在數據庫中的類和NOT NULL標記爲'nullable = false',但它不基於一個序列。 很可能''em.find()'的sql是用'SOURCE_SYSTEM ='''生成的,而不是'SOURCE_SYSTEM IS NULL',這就是爲什麼記錄沒有被正確返回的原因。 –