如何使用JPA为第三个实体建立约束?

时间:2013-01-10 18:43:18

标签: hibernate jpa persistence

所以,我有一个包含三个实体的模型:文档模板 Origin

我的问题的主要原因是我需要文档数字对于模板是唯一的来源,但由于原点是Template(不属于Document)的属性,我无法以直接的方式为其创建唯一约束。

为了澄清一下,代码中的模型是这样的:

产地:

@Entity
public class Origin {
    @Id private Long id;
    // ... some other fields
}

模板:

@Entity
public class Template {
    @Id private Long id;
    @Column private Origin origin;
    // ... some other fields
}

文件:

@Entity
public class Document {
    @Id private Long id;
    @Column Template template;
    @Column Long number;
    // ... some other fields
}

因此,Origins有几个关联的模板,您可以使用模板为Origin创建文档。

正如我所说,我的问题的根源是文档的数字对于每个来源必须是唯一的。 我能想到的唯一方法就是为 originId 使用一个额外的字段,并尝试保持更新。

所以,我试图做这样的事情:

@Entity
@Table("documents",
     uniqueConstraints = @UniqueConstraint(columnNames = {"number", "originId"}))
public class Document {
    @Id private Long id;
    @Column Template template;
    @Column Long number;
    // ... some other fields

    // added extra field to use in the constraint:
    @Column Long originId;

    @PrePersist
    @PreUpdate
    private void updateConstraintValue() {
        this.originId = getTemplate().getId();
    }
}

注意:为了简洁而省略了getter,setter和其他样板

但是这并不总是适用于JPA,因为在持久化/更新事件发生时,模板对象不需要是一个被管实体(它只需要为关系设置一个id)

然后我现在认为这可能不是最好的方法。所以,我的问题是:

  • 我还有其他选择吗? JPA(或Hibernate)API有更好的方法来处理这个问题吗? (我正在使用JPA 2和Hibernate 3.6.10,顺便说一句)
  • 我是否应该只信任客户端代码以使用具有正确id的Origin对象传递Template对象(即使它可能与数据库中的不同)?
  • 我是否可以更好地在Origin中映射Origin本身,并相信客户端代码以使其与模板同步?

1 个答案:

答案 0 :(得分:1)

我可能会遗漏一些东西,但是你可以完全摆脱原始ID并简单地使用生成的ID而不是手动创建一个ID吗?你已经有了一个ID列。看起来您需要做的就是指定生成ID。

@Entity
@Table("documents" )
public class Document {
    @Id 
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    private Long id;

    @Column Template template;

    @Column Long number;
    // ... some other fields

}

注意:我添加了GeneratedValue注释并删除了原始ID