【问题标题】:How do I express this constraint with JPA?如何用 JPA 表达这个约束?
【发布时间】:2011-11-01 07:06:28
【问题描述】:

我有一个如下所示的课程:

public enum Scope {
  A, B, C...
}

@Entity
public class User {

    ...

    Scope scope; // enum, see above

    @ElementCollecton
    List<Long> numbers;

    ...
}

我的问题是我不知道如何使用 JPA 或直接在我的 Postgres 数据库中表达以下约束: 范围为 x 且编号为 y 的用户只能有一个。

为了澄清我的意思,一些伪代码:

这是有效的(Bobs 3 不会与 Toms 3 发生冲突,因为 Bob 具有不同的作用域): 汤姆(范围=A,数字=[1,2,3,4]),卡尔(范围=A,数字=[5,6,7]),鲍勃(范围=B,数字=[3, 42, 100 ])

但这是无效的(Carls 4 违反了约束,因为 Tom 具有相同的范围并且在他的列表中也是 4): Tom(scope=A,numbers=[1,2,3,4]), Carl(scope=A,number=[4,5,6,7]), Bob(scope=B,numbers=[3, 42 , 100])

【问题讨论】:

  • 感谢 JEE6 引入的 bean 验证,您可以使用所需的任何验证逻辑构建自定义验证器。可以在这里找到一个简单的例子(只是从谷歌结果中快速挑选出来的):silentwalker.wordpress.com/2009/04/07/…
  • 这看起来像是一个答案@ifischer..
  • 自定义验证器将在 java 级别强制执行约束,但看起来 popopaule 正在寻找数据库级别的约束。
  • 自定义验证器还必须执行查询才能进行验证,这通常是不可取的
  • 感谢您的意见,但 Affe 是正确的。我需要一个数据库级别的约束。

标签: java postgresql jpa jpa-2.0


【解决方案1】:

你可以做的一件事是在元素集合的外键上向 JPA 撒谎,然后对集合表中范围 + 数字的组合施加一个普通的唯一约束。

@Column(name="SCOPE")
@Enumerated(EnumType.STRING)//or whatever
private Scope scope;

@ElementCollection
@CollectionTable(name= "NUMBERS" ,
    joinColumns={ @JoinColumn(name = "USER_ID", referencedColumnName = "ID"),
                  @JoinColumn(name = "USER_SCOPE", referencedColumnName = "SCOPE") }),
@Column(name="NUMBER")
private List<Long> numbers;

显然 USER_SCOPE 在规范化模型中是完全不需要的,但通过告诉 JPA 它是密钥的一部分,您可以欺骗提供者为您维护列。

【讨论】:

    猜你喜欢
    • 2013-01-18
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    相关资源
    最近更新 更多