具有空值的 JPA 复合主键
2022-09-03 16:17:12
我有一个表,其中包含 oracle 数据库中的客户数据。下面是一个简化的定义:
CUSTOMER (CUSTOMER_ID NUMBER NOT NULL,
SOURCE_SYSTEM VARCHAR2(30),
FULL_NAME VARCHAR2(360),
PHONE_NUMBER VARCHAR2(240)
)
此表的主键是 。(CUSTOMER_ID, SOURCE_SYSTEM)
该表具有许多行,其为 null。在数据库级别,没有问题,但是当我尝试通过JPA实体访问这些行中的任何一个时,它会导致许多问题:SOURCE_SYSTEM
1:使用以 null 读取行始终会导致返回 null。em.find()
SOURCE_SYSTEM
2:如果表中不存在记录,则使用空值的行进行更新插入会成功,但在后续更新时会失败,因为合并始终会导致运行插入。em.merge()
SOURCE_SYSTEM
3:用于显式查询具有 null 的行会导致以下异常: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 类:
客户.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
...
}