【问题标题】:How does EclipseLink name foreign keys?EclipseLink 如何命名外键?
【发布时间】:2019-04-02 14:20:23
【问题描述】:

我在我的 Java 项目中使用 EclipseLink 2.6.2 和 Oracle。我想了解 EclipseLink 如何决定命名外键。

目前,当我启动我的应用程序时,我收到约束名称已存在的错误。我可以查询数据库并查看创建的外键是什么,我看到一个具有相同名称的外键,但我不清楚它是如何创建名称的。显然是去掉了所有元音,但它是使用表一和表二,还是使用列名?

这是错误:

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-02264: name already used by an existing constraint
Error Code: 2264
Call: ALTER TABLE publctncompntdef_hist_ref ADD CONSTRAINT pblctncmpntdfbdpckCmpnntDfntnd FOREIGN KEY (bidpackComponentDefinitionId) REFERENCES bidpckcompntdef (bidpackComponentDefinitionId)

它试图创建的外键名称是:pblctncmpntdfbdpckCmpnntDfntnd

它正在尝试为表 publctncompntdef_hist_ref 创建一个外键,该表的列 bidpackComponentDefinitionId 引用表 bidpckcompntdef 和列 bidpackComponentDefinitionId强>

但它已经为表 publctncompntdefref 创建了一个同名的外键,其中列 bidpackComponentDefinitionId 到表 bidpckcompntdef 和列 bidpackComponentDefinitionId

我已经用谷歌搜索过,但似乎找不到有关外键命名策略的文档。

另外,这里是@JoinTable 值:

@JoinTable(name = "publctncompntdef_hist_ref",
           joinColumns={@JoinColumn(name="publicationHistoryId",referencedColumnName="id")},
           inverseJoinColumns={@JoinColumn(name="bidpackComponentDefinitionId",referencedColumnName="bidpackComponentDefinitionId")})

@JoinTable(name = "publctncompntdefref",
        joinColumns={@JoinColumn(name="bidpackComponentDefinitionId",referencedColumnName="bidpackComponentDefinitionId")},
        inverseJoinColumns={@JoinColumn(name="publicationId",referencedColumnName="id")})

【问题讨论】:

  • pblctncmpntdfbdpckCmpnntDfntnd 的长度为 30 个字符,这是 oracle 的限制(除非您使用启用了扩展名称语义的 Oracle 12cR2)。但这是一个可怕的名字,你最好不要有一个名字,而是让 Oracle 生成一个SYS_ 名字。不知道你是如何说服 EclipseLink 这样做的。
  • 完全同意你的看法。而且,不幸的是,我正在使用 Oracle 12cR1。

标签: java oracle jpa foreign-keys eclipselink


【解决方案1】:

我想我明白了。最初我并没有意识到 EclipseLink 是开源的,但我终于发现并从以下位置下载了代码:https://github.com/eclipse/eclipselink.runtime

基本上它似乎做的是

  1. 如果 FK_ + 表名 + _ + 列名大于限制(Oracle 为 30 个字符),则删除 FK_ 前缀。
  2. 如果仍然太长,请删除所有下划线或任何非字母或数字的内容。
  3. 如果还是太长,去掉元音
  4. 如果仍然太长:
    4a。检查没有元音的列名是否大于限制(30 个字符)。如果是这样,使外键名称只是列名称减去元音,从末尾截断为最大大小
    4b。否则,将表名截断为剩余的字符数(最大限制 - 列名长度)

以下是我的情况:
表名 = publctncompntdefref (19chars) 和列名 = bidpackcomponentdefinitionid (28chars)
减去元音 = pblctncmpntdfrf(15 个字符)和 bdpckcmpnntdfntnd(17 个字符)
连接这两个给我们 32 个字符。由于没有元音的列名少于 30 个字符(oracle 最大),因此将表名截断为(30-17 = 13 个字符),即 pblctncmpntdf。整个外键名是 pblctncmpntdfbdpckcmpnntdfntnd。

类似地,当我有表名 = publctncompntdef_hist_ref 和列名 = bidpackcomponentdefinitionid,没有元音时,我最终得到了 pblctncmpntdfhstrf 和 bdpckcmpnntdfntnd。表名称为 18 个字符,列名称为 17 个字符。因此需要将表截断为 13 个字符,因此 pblctncmpntdfhstrf 变为 pblctncmpntdf,整个外键变为 pblctncmpntdfbdpckcmpnntdfntnd。

这解释了为什么 EclipseLink 告诉我已经有一个具有该名称的外键约束。

【讨论】:

    猜你喜欢
    • 2011-09-05
    • 2010-09-17
    • 2020-02-24
    • 2011-03-29
    • 2021-02-04
    • 2013-02-12
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多