`@JoinTable`注解中的`foreignKey`和`inverseForeignKey`是什么意思?

huangapple go评论77阅读模式
英文:

What is foreignKey and inverseForeignKey in @JoinTable annotation?

问题

以下是您提供的代码的翻译部分:

@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@EqualsAndHashCode
@ToString(callSuper = true)
@IdClass(QuarantinePolicyIdentity.class)
@Entity(name = PolicyServiceConstants.QUARANTINE_POLICY_TABLE)
@Table(uniqueConstraints = @UniqueConstraint(name = PolicyServiceConstants.QUARANTINE_POLICY_UNIQUE_NAME_CONSTRAINT,
        columnNames = {"customerUuid", "name"}),
        indexes = {@Index(name = PolicyServiceConstants.QUARANTINE_POLICY_UNIQUE_INDEX,
                columnList = "orderNo",
                unique = false)
        })
public class QuarantinePolicyEntity {

    @Id
    private String quarantinePolicyId;

    @Id
    @JsonIgnore
    private String customerUuid;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @JoinTable(name = PolicyServiceConstants.QUARANTINE_POLICY_OUTBOUND_RULE_TABLE,
            foreignKey = @ForeignKey(name = PolicyServiceConstants.FOREIGN_KEY_QUARANTINE_POLICY_QPOR),
            inverseForeignKey = @ForeignKey(name = PolicyServiceConstants.FOREIGN_KEY_QUARANTINE_POLICY_ORQP))
    private Set<RuleEntity> outboundRules;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @JoinTable(name = PolicyServiceConstants.QUARANTINE_POLICY_INBOUND_RULE_TABLE,
            foreignKey = @ForeignKey(name = PolicyServiceConstants.FOREIGN_KEY_QUARANTINE_POLICY_QPIR),
            inverseForeignKey = @ForeignKey(name = PolicyServiceConstants.FOREIGN_KEY_QUARANTINE_POLICY_IRQP))
    private Set<RuleEntity> inboundRules;

    private String createdBy;

    private Date createdDate;

    private String lastModifiedBy;

    private Date lastModifiedDate;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof QuarantinePolicyEntity)) return false;
        QuarantinePolicyEntity that = (QuarantinePolicyEntity) o;
        return com.google.common.base.Objects.equal(getQuarantinePolicyId(), that.getQuarantinePolicyId()) &&
                com.google.common.base.Objects.equal(getCustomerUuid(), that.getCustomerUuid());
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), quarantinePolicyId, customerUuid);
    }

}

请注意,这是您提供的代码的简单翻译,其中的注解和变量名等保持不变。对于您提到的问题:

  • @JoinTable 注解用于指定连接两个实体之间关系的中间表信息。foreignKeyinverseForeignKey 是用来指定外键的约束的,分别用于指定在中间表中哪个外键引用哪个实体。在这种情况下,它们是通过注解中的 name 属性引用外键约束的名字,这些约束应该在其他地方定义。

  • 关于如何指定外键和关联表的问题,@JoinTable 注解中的 foreignKeyinverseForeignKey 通过引用外键约束的名字来实现。外键约束的名字应该在其他地方定义,通常是在实体类之外的地方,可能是在数据库迁移脚本或配置文件中。

请注意,这只是代码的简单翻译,某些上下文可能会影响更详细的解释。

英文:

I am having a project where I found, a schema something like this

@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@EqualsAndHashCode
@ToString(callSuper = true)
@IdClass(QuarantinePolicyIdentity.class)
@Entity(name = PolicyServiceConstants.QUARANTINE_POLICY_TABLE)
@Table(uniqueConstraints = @UniqueConstraint(name = PolicyServiceConstants.QUARANTINE_POLICY_UNIQUE_NAME_CONSTRAINT,
columnNames = {&quot;customerUuid&quot;, &quot;name&quot;}),
indexes = {@Index(name = PolicyServiceConstants.QUARANTINE_POLICY_UNIQUE_INDEX,
columnList = &quot;orderNo&quot;,
unique = false)
})
public class QuarantinePolicyEntity {
@Id
private String quarantinePolicyId;
@Id
@JsonIgnore
private String customerUuid;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@JoinTable(name = PolicyServiceConstants.QUARANTINE_POLICY_OUTBOUND_RULE_TABLE,
foreignKey = @ForeignKey(name = PolicyServiceConstants.FOREIGN_KEY_QUARANTINE_POLICY_QPOR),
inverseForeignKey = @ForeignKey(name = PolicyServiceConstants.FOREIGN_KEY_QUARANTINE_POLICY_ORQP))
private Set&lt;RuleEntity&gt; outboundRules;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@JoinTable(name = PolicyServiceConstants.QUARANTINE_POLICY_INBOUND_RULE_TABLE,
foreignKey = @ForeignKey(name = PolicyServiceConstants.FOREIGN_KEY_QUARANTINE_POLICY_QPIR),
inverseForeignKey = @ForeignKey(name = PolicyServiceConstants.FOREIGN_KEY_QUARANTINE_POLICY_IRQP))
private Set&lt;RuleEntity&gt; inboundRules;
private String createdBy;
private Date createdDate;
private String lastModifiedBy;
private Date lastModifiedDate;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof QuarantinePolicyEntity)) return false;
QuarantinePolicyEntity that = (QuarantinePolicyEntity) o;
return com.google.common.base.Objects.equal(getQuarantinePolicyId(), that.getQuarantinePolicyId()) &amp;&amp;
com.google.common.base.Objects.equal(getCustomerUuid(), that.getCustomerUuid());
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), quarantinePolicyId, customerUuid);
}
}
  • I am not able to understand what is foreignKey and inverseForeignKey in @JoinTable.
  • Secondly, do we have to mention the FK, RuleEntity table, as how does it know which FK to take?

Thanks.

答案1

得分: 1

JPA文档中是怎么说的?

如果你访问JoinTable注解文档,你会发现

> foreignKey(可选)用于在表生成生效时指定或控制与joinColumns元素对应的列的外键约束生成。
>
> inverseForeignKey(可选)用于在表生成生效时指定或控制与inverseJoinColumns元素对应的列的外键约束生成。

你真的需要这些吗?

因此,你可以看到这两个属性在模式生成期间定义了外键约束的创建。而不是外键本身。外键是使用joinColumnsinverseJoinColumns属性来定义的。

现在,如果你不设置foreignKeyinverseForeignKey,那么默认值是ConstraintMode.PROVIDER_DEFAULT,这意味着你使用的数据库(这里是Oracle)将决定外键约束的名称。

所以,除非你有需要,否则你实际上不需要显式地提供foreignKeyinverseForeignKey。这些都是可选属性。

改善关联的更多方法

  • 我不知道这是否是可用的代码。但实际上,这里的OneToMany关联没有正确定义。没有joinColumnsinverseJoinColumns关联(因此没有告诉哪些列进行映射)。关联应该这样定义
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@JoinTable(name = "join_table_name",
           joinColumns = @JoinColumn(name = "column_a"),
           inverseJoinColumns = @JoinColumn(name = "column_b"),
           foreignKey = @ForeignKey(name = "name_of_the_constraint_for_column_a"),
           inverseForeignKey = @ForeignKey(name = "name_of_the_constraint_for_column_b"))
private Set<RuleEntity> outboundRules;
  • 此外,甚至对于OneToMany关联,你也不需要一个JoinTable。仅一个JoinColumn就足够了。思考关联是单向的还是双向的,或者哪一侧是关系的拥有方。你会找到许多选项来优化你的关联。

更多阅读:

英文:

What does the JPA documentation say?

If you visit the JoinTable annotation doc you will find

> foreignKey (Optional) Used to specify or control the generation of a foreign key constraint for the columns corresponding to the
> joinColumns element when table generation is in effect.
>
> inverseForeignKey (Optional) Used to specify or control the generation of a foreign key constraint for the columns corresponding
> to the inverseJoinColumns element when table generation is in effect.

Do you really need these?

So you can see these two attributes are defining the foreign key contraint creation during schema generation. Not the foreign key itself. The foreign keys are defined with the joinColumns and inverseJoinColumns attribute.

Now if you dont put those foreignKey and inverseForeignKey, then the default value is ConstraintMode.PROVIDER_DEFAULT that means the database you are using (Oracle here) will decide the name of the foreign key constraint.

So you dont really need to explicitly provide the foreignKey and inverseForeignKey unless you want. These are optional attribute.

More ways to improve the association

  • I dont know wheather its a working code or not. But actually the OneToMany association is not properly defined here. There is no joinColumns and inverseJoinColumns association (so nothing is telling which column to map). The association should be defined this way

      @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @JoinTable(name = &quot;join_table_name&quot;,
    joinColumns = @JoinColumn(name = &quot;column_a&quot;),
    inverseJoinColumns = @JoinColumn(name = &quot;column_b&quot;),
    foreignKey = @ForeignKey(name = &quot;name_of_the_constraint_for_column_a&quot;),
    inverseForeignKey = @ForeignKey(name = &quot;name_of_the_constraint_for_column_b&quot;))
    private Set&lt;RuleEntity&gt; outboundRules;
    
  • Moreover you dont even need a JoinTable for a OneToMany association either. Simply a JoinColumn should do the job. Think about the association, if its unidirectional or bi directional or which side is the owning side of the relationship. You will find handful of options to optimize your association.

More read:

huangapple
  • 本文由 发表于 2020年8月18日 21:18:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/63469521.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定