JPA 可嵌入 PK 和可为空的字段
Posted
技术标签:
【中文标题】JPA 可嵌入 PK 和可为空的字段【英文标题】:JPA Embeddeble PK and nullable field 【发布时间】:2014-05-23 09:03:27 【问题描述】:我有一个名为“属性”的表,它有 3 个字段的 PK 可以为空。在这种情况下 Style_no 不为空,但 item_no 和 size_no 为空。
是否可以有一个Embeddeble PK,其中字段可以为空?
@Entity
@Table(name="ATTRIBUTE")
public class Attribute
@EmbeddedId
private AttributePK attrPK;
...
@Embeddable
public static class AttributePK implements Serializable
private static final long serialVersionUID = -2976341677484364274L;
@Column(name="STYLE_NO", nullable=true)
protected String styleNo;
@Column(name="ITEM_NO", nullable=true)
protected String itemNo;
@Column(name="SIZE_NO", nullable=true)
protected String sizeNo;
...
当我尝试引用一个字段时,例如style_no 结果数量为0。
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, orphanRemoval=true, mappedBy="attrPK.styleNo")
@MapKey(name="attrPK.name")
public Map<String,Attribute> attributesX;
或
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="STYLE_NO", referencedColumnName="STYLE_NO")
private List<Attribute> attributes;
当我将 item_no 和 size_no 作为 pk 删除时,我收到了有效的结果。
编辑: 为了让我的问题更具体。是否允许根据 JPA 指南或“常识”对 EmbeddebedId 使用可为空的字段?如果没有,我需要添加哪些注释或逻辑才能使其在不添加另一个 PK 的情况下工作? 一旦用值填充 PK 中的可为空字段。结果是正确的。
非常感谢!
【问题讨论】:
【参考方案1】:既然you must not use null in your PK,这就是你应该做的:
-
添加surrogate primary key。
你仍然可以通过二分索引(在 PostgreSQL 中)实现唯一性约束和默认 PK 索引:
在 my_table (Style_no, item_no, size_no) WHERE (item_no IS NOT NULL AND size_no IS NOT NULL) 上创建唯一索引 style_item_size_idx;
【讨论】:
谢谢,但是,我明确地询问了一个没有添加另一个 id 的解决方案 - “..它可以在不添加另一个 PK 的情况下工作..”。 我明白,只是这是您需要注意的数据库限制。 当然,我上面的例子只是为了找出 Hibernate 作为一个额外的层,是否可以避免这种特定于 DB 的边界。没有真正的用例。 these reasons 总是选择 Hibernate,否则我只会使用具有强大查询能力的 JOOQ。【参考方案2】:看看here 似乎, (NULL == NULL) -> false 的答案与您的问题有关。
【讨论】:
谢谢你的链接。但是正如下面的 cmets 正确提到的那样,它并不令人满意。例如。从 JPA 开始,它不允许在可以为空的字段上使用 Id。但我找不到 EmbeddedId 的相同限制。我所需要的是,如果有一种解决方法,而不添加另一个人工 ID 或指向源的链接,该链接表明 EmbeddedId 中的可为空字段是不允许的。【参考方案3】:通常复合 pk 不允许在数据库中有空值。
技术上我们会说:为什么不呢,null
也可以是一个值。
DB-Analyst 会问:好的,如果我排序 1,2,3,4,null
,5。你说null
是在1之前还是5之后?
因此 PostgreSQL、Oracle、mysql 将不支持复合主键中的空值。
【讨论】:
1) 对于订单,我会说数据库可以自行决定。从技术上讲,它在任何地方定义都很重要。 2) 是的,不允许 PK 约束。对于 UNIQUE 约束,它是允许的,但它仍然不适用于休眠。 @MortalFool 你是对的,我添加了最后一个单词:primary
以清除键和主键之间的区别。【参考方案4】:
JPA 准则或“常识”不允许为 EmbeddebedId 使用可为空的字段?如果没有,我需要添加哪些注释或逻辑才能使其在不添加另一个 PK 的情况下工作?
答案如下
@EmbeddedId
private AttributePK attrPK;
不允许主键为空。
所以要做到这一点,请使用下面的另一个注释
@IdClass(AttributePK.class)
private AttributePK attrPK;
【讨论】:
谢谢,我明天试试验证。 IdClass 有一个@Target(ElementType.TYPE)
,你怎么能把它放在一个字段上???以上是关于JPA 可嵌入 PK 和可为空的字段的主要内容,如果未能解决你的问题,请参考以下文章