Почему JPA выбирает String для JoinColumn независимо от типа ключа? - PullRequest
4 голосов
/ 24 октября 2010

Использование реализации EclipseLink JPA2 (не уверен, что то же самое с реализацией Hibernate)

У меня есть простая структура, в которой у организации есть контракты. Вот SQL, который я экспортировал из postgres для создания Организации

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 ]

4 голосов
/ 26 октября 2010

Я считаю, что проблема заключается в чувствительности к регистру.

Вы не установили @Column для атрибута идентификатора ключа, поэтому имя столбца по умолчанию - "KEY". В вашем @ManyToOne вы ссылались на «ключ», который не является тем же столбцом, поэтому EclipseLink (который чувствителен к регистру и поддерживает ссылки на внешние ключи без идентификатора) предположил, что это был другой столбец, о котором он не знал, поэтому дал это тип по умолчанию VARCHAR.

Либо измените referencedColumnName на «KEY», либо удалите его, так как это не требуется при ссылке на одиночный идентификатор.

Было бы целесообразно зарегистрировать ошибку в EclipseLink о том, что должно быть зарегистрировано предупреждение, когда ссылка на столбец не найдена или имеет неправильный регистр (возможно, даже автоматически переключает регистр). На самом деле, возможно, мы уже записали предупреждение, вы можете проверить свой журнал.

3 голосов
/ 24 октября 2010

Нереально ли ожидать, что он получит правильный тип столбца?

Нет, это не нереально, и текущий результат явно неожидан.

Я использую это неправильно или у меня неправильные ожидания?

Ваши отображения не выглядят неправильно. Не могли бы вы попробовать следующее и подтвердить, что вы получите тот же результат (я просто опускаю 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?

Номер * * тысяча двадцать-одна

...