首页 > 解决方案 > 如何设置类级别 jpa 检查约束的名称

问题描述

我想在 JPA 中对实体定义一个约束,以确保将两个属性“text”或“title”之一设置为非空值。

对于此示例,假设以下 Question 实体类:

@Entity
@Table
public class Question {

@Id
private Long id;

@Column(nullable = true)
private String text;

@Column(nullable = true)
private String title;

}

对于这个类,JPA 会生成如下 SQL 语句(我们需要使用 oracle 方言):

    create table question (
        id number(19,0) not null,
        text varchar2(50 char) null,
        title varchar2(10,0) null,
        primary key (id)
    );


为了检查是否设置了任一属性,我可以添加一个检查约束:

@Entity
@Table
@Check(constraints = "TEXT IS NOT NULL OR TITLE IS NOT NULL")    
public class Question {
...
}

现在 JPA 将生成这个:

    create table question (
        id number(19,0) not null,
        text varchar2(50 char) null,
        title varchar2(10,0) null,
        primary key (id),
        check (TEXT IS NOT NULL OR TITLE IS NOT NULL)
    );

在数据库端,这将生成一个带有随机名称的检查约束,例如“SYS_C00127157”。

为了给约束分配一个有意义的名称(例如:check_title),我可以使用这个 DDL:

    create table question (
        id number(19,0) not null,
        text varchar2(50 char) null,
        title varchar2(10,0) null,
        primary key (id),
        constraint check_title check(TEXT IS NOT NULL OR TITLE IS NOT NULL)
    );

我正在寻找的是这样的:

@Entity
@Table
@Check(name = "check_title" constraints = "TEXT IS NOT NULL OR TITLE IS NOT NULL")    
public class Question {
...
}

不幸的是,这是不可能的。Java 中的 @Check 注释没有为约束提供这样的名称属性。

有没有其他方法可以设置名称,以便生成的 DDL 匹配预期结果?

标签: javaoraclehibernatejpa

解决方案


不幸的是,这是不可能的。如果您看一下表生成脚本是如何构建的:

https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/mapping/Table.java#L604

@Check你会看到你在注解中指定的字符串是这样包装的:

buf.append( ", check (" )
    .append( checkConstraint )
    .append( ')' );

并将约束名称的生成提供给数据库。

相比之下,上面几行,您会发现可能会影响唯一约束的名称。在这里你可以找到它的一个例子。


推荐阅读