为什么JPA为JoinColumn选择String而不管密钥类型?

时间:2010-10-23 20:45:55

标签: java postgresql jpa eclipselink jpa-2.0

使用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
}

2 个答案:

答案 0 :(得分:4)

我认为问题是区分大小的问题。

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

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

在EclipseLink上记录一个错误是值得的,当找不到列引用时,应该记录警告,或者错误的情况(甚至可能自动切换案例)。实际上我们可能已经记录了警告,你可能希望查看你的日志。

答案 1 :(得分:3)

  

我希望它能获得正确的列类型是不现实的吗?

不,这不是不现实的,目前的结果显然是出乎意料的。

  

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

您的映射看起来没错。您可以尝试以下方法并确认您得到相同的结果(我只是省略了您不应该定义的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?

没有