【问题标题】:Why is JPA choosing String for JoinColumn regardless of key types?为什么无论键类型如何,JPA 都为 JoinColumn 选择 String?
【发布时间】:2011-04-29 16:35:26
【问题描述】:

使用 EclipseLink JPA2 实现(不确定是否与 Hibernate 实现相同)

我有一个简单的结构,其中组织实体有合同。这是我从 postgres 导出的用于创建组织的 sql

CREATE TABLE organization (
    key bigint NOT NULL,
    version integer
);

如果我这样指定组织的合同方:

@ManyToOne( optional=false )
@JoinColumn( name="organization_key", referencedColumnName="key" )
private Organization organization;

然后转储我得到的架构。

CREATE TABLE contract ( 
    key bigint NOT NULL, 
    version integer, 
    organization_key character varying(255), 
);

对我来说,使用字符变量(255)字段来引用组织键是没有意义的。我知道我可以按如下方式使用 columnDefinition:

@ManyToOne( optional=false )
@JoinColumn( name="organization_key", referencedColumnName="key", columnDefinition="bigint NOT NULL" )
private Organization organization;

获取 bigint 类型而不是字符类型。

期望它获得正确的列类型对我来说是不现实的吗?是我用错了,还是我有错误的期望?我是否每次都必须使用 columnDefinition?

更新: 这是来自组织实体的相关信息

@Entity
@Table( name = "organization" )
@SequenceGenerator( name = "ORGANIZATION_SEQ_GEN", sequenceName = "ORGANIZATION_SEQUENCE" )
public class Organization
        implements DataObject<Long>
{

    /**
     * key for this instance. Should be managed by JPA provider.
     */
    @Id
    @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "ORGANIZATION_SEQ_GEN" )
    private Long key;

    /**
     * JPA version column
     */
    @Version
    protected int version;

    /**
     * All contracts for this organization
     */
    @OneToMany(mappedBy="organization" )
    @OrderBy( "endDate DESC" )
    private List<Contract> contracts;

    ... getters and setters        
 }

这是合同实体

@Entity
@Table( name = "contract" )
@SequenceGenerator( name = "CONTRACT_SEQ_GEN", sequenceName = "CONTRACT_SEQUENCE" )
public class Contract
        implements DataObject<Long>
{

    /**
     * key for this instance. Should be managed by JPA provider.
     */
    @Id
    @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "CONTRACT_SEQ_GEN" )
    private Long key;

    /**
     * Organization that owns this contract, required.
     */
    @ManyToOne( optional=false )
    @JoinColumn( name="organization_key", referencedColumnName="key" )
    private Organization organization;

    /**
     * JPA version column
     */
    @Version
    protected int version;

    ... getters and setters
}

【问题讨论】:

    标签: java postgresql jpa eclipselink jpa-2.0


    【解决方案1】:

    期望它获得正确的列类型对我来说是不现实的吗?

    不,这并非不现实,而且目前的结果显然出乎意料。

    是我用错了,还是我有错误的期望?

    您的映射看起来没有错。您是否可以尝试以下操作并确认您得到相同的结果(我只是省略了您不应该定义的referencedColumnName)?

    @Entity
    @Table( name = "contract" )
    @SequenceGenerator( name = "CONTRACT_SEQ_GEN", sequenceName = "CONTRACT_SEQUENCE" )
    public class Contract implements DataObject<Long> {
        @Id
        @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "CONTRACT_SEQ_GEN" )
        private Long key;
        ...
        @ManyToOne( optional=false )
        @JoinColumn( name="organization_key" )
        private Organization organization;
        ...
    }
    

    我没有安装PostgreSQL,不能自己尝试。

    预计我每次都必须使用 columnDefinition 吗?

    没有。

    【讨论】:

    • @digitaljoel:查看我的更新。顺便说一句,您是否在 persistence.xml 中定义了 eclipselink.target-database 属性? eclipselink.ddl-generation的值是多少?
    • 感谢您对 Pascal 的帮助。 而我的 ddl-gneration 是 drop-and-create-tables,而我正在搞砸这些东西。一旦我得到它的工作,我只是把它完全注释掉。现在删除referencedColumnName...
    • 有趣,有这个:@ManyToOne( optional=false ) @JoinColumn( name="organization_key" ) 私有组织组织;我明白了: CREATE TABLE contract (key bigint NOT NULL, version integer, organization_key bigint, );看来你已经解决了我的问题!
    • @digitaljoel:很高兴它在没有定义 referencedColumnName 的情况下工作,尽管我发现这种行为很奇怪。您的映射没有错 IMO,听起来像一个错误。
    • 我同意。似乎没有引用的列,即使它是多余的,也不应该导致它像那样映射。感谢您的想法和快速响应,我很感激。
    【解决方案2】:

    我认为问题在于区分大小写。

    您没有在键 id 属性上设置@Column,因此默认列名称是“KEY”。 在您的@ManyToOne 中,您引用了“key”,它不是同一列,因此 EclipseLink(区分大小写并支持非 Id 外键引用)假设这是一个不同的列,并且它不知道,所以给了它是 VARCHAR 的默认类型。

    要么将 referencedColumnName 更改为“KEY”,要么将其删除,因为在引用单例 Id 时不需要它。

    在 EclipseLink 上记录一个错误是值得的,即当未找到列引用或大小写错误时应记录警告(甚至可能自动切换大小写)。实际上,我们可能已经记录了警告,您不妨检查一下您的日志。

    【讨论】:

    • 啊,有道理。我不知道 EL 区分大小写。感谢您对此有所了解。
    猜你喜欢
    • 2020-04-24
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    相关资源
    最近更新 更多