我有一个Product
实体,name
和category
组合对于每个产品都应该是唯一的。
在我的情况下,name
是必需的,但category
可能不存在。
Product
的定义如下:
@Entity
@Table(
uniqueConstraints=
@UniqueConstraint(columnNames={"name", "category")
)
public class Product {
// ...
@NotNull
@Size(min = 1, max = 64)
private String name;
@ManyToOne(fetch = FetchType.EAGER)
private ProductCategory category;
// ...
}
...但只有当类别不是NULL
时,约束才有效。
换句话说,我不能坚持(这没关系)实体:
name="example", category=1
name="example", category=1
...同时我可以坚持(这不是我想要的)实体wihh:
name="example", category=null
name="example", category=null
所以,我的问题是 - 如何为字段组合实现唯一约束,其中一个字段可以为空(将NULL
视为任何其他值)?
PS:我使用Hibernate作为JPA提供程序和MySQL数据库。
答案 0 :(得分:0)
@UniqueConstraints
注释应该完成工作。使用示例检查the documentation。此外,如果表是自动生成的,您可以考虑删除表,具体取决于您在persistence.xml
文件中设置架构自动生成的方式。
<强>更新强> 当然,您必须指定两个列(而不是您所做的字段):
@UniqueConstraint(columnNames={"name", "category_id")//or check the name of the column in the db for category
更新2 因为问题实际上是在mysql中,所以可以在实体中插入其他两个持久字段:
@Column(columnName="category", insertable=false, updatable=false)//map to the same column used for your category
private Long categoryId;//I suppose it is a Long.
@Column(columnName="categoryIdConstraint")//
private long categoryIdConstraint;//this is not nullable. If categoryId is null, then simply put 0 or -1
//and now synchronize the categoryIdConstraint field with entity listeners
//and add the @UniqueConstraint over "name" and "categoryIdConstraint" (which now cannot be null.)
答案 1 :(得分:0)
管理以避免相对容易地解决这个问题(通过应用空对象模式)。
对于任何无法轻易避免此问题的人,并且想知道如何以尽可能少的痛苦来解决这个问题 - 请看一下实现mysql trigger,它将执行考虑可以为空的列的唯一约束验证。 Here是一个很好的起点。