java 具有空值的 JPA 复合主键

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15687837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 20:31:02  来源:igfitidea点击:

JPA composite primary key with null value

javajpaeclipselinkjpa-2.0ejb-3.0

提问by Matsu Q.

I have a table containing customer data in an oracle database. Here is a simplified definition:

我在 oracle 数据库中有一个包含客户数据的表。这是一个简化的定义:

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

The primary key for this table is (CUSTOMER_ID, SOURCE_SYSTEM).

该表的主键是(CUSTOMER_ID, SOURCE_SYSTEM)

The table has numerous rows for which SOURCE_SYSTEMis null. At the database level, there is no issue, however when I try to access any of these rows via JPA Entity, it causes a number of issues:

该表有许多SOURCE_SYSTEM为空的行。在数据库级别,没有问题,但是当我尝试通过 JPA 实体访问这些行中的任何一行时,它会导致许多问题:

1: Using em.find()to fetch a row with a null SOURCE_SYSTEMalways results in a null being returned.

1:使用em.find()空值获取一行SOURCE_SYSTEM总是导致返回空值。

2: Using em.merge()to upsert a row with a null SOURCE_SYSTEMsucceeds if the record does not exist in the table, but fails on subsequent updates because the merge ALWAYS results in an insert being run.

2:如果记录不存在于表中,则使用em.merge()更新插入具有空值的行会SOURCE_SYSTEM成功,但在后续更新时失败,因为合并总是会导致运行插入。

3: Using em.createQuery()to explicitly query for a row with a null causes the following exception:

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))")

Unfortunately, "Primary keys must not contain null" seems pretty final. I was unable to find too much information on workarounds for this error, which makes it seem like there is no solution.

不幸的是,“主键不能包含空值”似乎是最终的。我无法找到有关此错误的解决方法的太多信息,这使得似乎没有解决方案。

THE QUESTION: I would like to know if anyone has any Java code-based solutionthat don't involve making changes to the database. My current workaround is to use ROW_IDas the @Idof the table, but this means I can no longer use em.merge()or em.find().

问题:我想知道是否有人有任何不涉及对数据库进行更改的基于 Java 代码的解决方案。我目前的解决办法是使用ROW_ID@Id表,但是这意味着我可以不再使用em.merge()em.find()

Here are my Java classes:

这是我的 Java 类:

Customer.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

客户 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
  ...
}

回答by James

Primary keys cannot contain null (in JPA or in databases). Use a different value such as "" or " ".

主键不能包含 null(在 JPA 或数据库中)。使用不同的值,例如“”或“”。

Is the customer_id unique? if so then just remove the sourceSystem from the Id.

customer_id 是唯一的吗?如果是这样,那么只需从 Id 中删除 sourceSystem。

Otherwise, you could try logging a bug to have support for null ids added.

否则,您可以尝试记录错误以添加对空 ID 的支持。