如何设置类级别的JPA检查约束的名称

时间:2019-06-18 09:37:19

标签: java oracle hibernate jpa

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

对于此示例,假设以下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注释没有为约束提供这样的 name 属性。

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

2 个答案:

答案 0 :(得分:0)

那不可能。

在我看来,从JPA批注生成生产数据库也不是一个好主意。 数据模型的寿命通常比应用程序长,因此最好控制DDL。

您应该考虑使用FlyWayLiquibase进行数据库迁移。

答案 1 :(得分:0)

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

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( ')' );

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

相反,a few lines above可以发现有可能影响唯一约束的名称。 Here,您可以找到它的示例。