Mysql @可空字段的唯一约束

Mysql @可空字段的唯一约束,mysql,sql,hibernate,jpa,unique-constraint,Mysql,Sql,Hibernate,Jpa,Unique Constraint,我有一个产品实体,它的名称和类别组合对于每个产品都应该是唯一的 在我的情况下,name是必需的,但是category可能不存在 产品的定义如下: @Entity @Table( uniqueConstraints= @UniqueConstraint(columnNames={"name", "category") ) public class Product { // ... @NotNull @Size(min = 1, max = 64)

我有一个
产品
实体,它的
名称
类别
组合对于每个产品都应该是唯一的

在我的情况下,
name
是必需的,但是
category
可能不存在

产品
的定义如下:

@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;

    // ...

}
。。。但该约束仅在category不是
NULL
时有效

换言之,我无法将实体持久化(这是可以的):

name="example", category=1
name="example", category=1
。。。同时,我可以通过以下方式保留实体(这不是我想要的):

name="example", category=null
name="example", category=null
所以,我的问题是-如何为字段组合实现唯一约束,其中一个字段可以为NULL(将
NULL
视为任何其他值)


PS:我使用Hibernate作为JPA提供程序和MySQL数据库。

使用
@UniqueConstraints
注释应该可以完成这项工作。请举例说明。同样,如果表是自动生成的,那么您可以考虑删除表,这取决于您在<代码>持久性.XML<代码>文件>中设置模式的自动生成。 更新 当然,必须同时指定这两列(而不是像以前那样指定字段):

更新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.)

设法避免相对容易地解决这个问题(通过应用空对象模式)


对于那些无法轻松避免此问题并想知道如何以尽可能少的痛苦解决此问题的人,请看一看将考虑可空列的唯一约束验证的实现。这是一个很好的起点。

嗯,我想应该是这样,但事实并非如此。这就是问题所在。阅读这样的问题:这似乎是MySQL特有的东西。但是我找不到解决方法。为什么不简单地设置一个默认类别呢?还是强制执行?这是我的B计划。但在我的情况下,这是一个相当棘手的解决方案,我想避免它。更新了答案。你可以对这个解决方案说同样的话,但这只是一个想法。
@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.)