Pergunta

Usando a implementação do Eclipselink JPA2 (não tenho certeza se é o mesmo com a implementação do Hibernate)

Tenho uma estrutura simples em que uma entidade organizacional tem contratos. Aqui está o SQL que exportei do Postgres para criar a organização

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

Se eu especificar o lado do contrato da organização como esta:

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

E então despeje o esquema, entendi isso.

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

Não faz sentido para mim que usaria um campo de personagem (255) para a referência à chave da organização. Eu sei que posso usar o ColumnDefinition da seguinte maneira:

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

Para obter o tipo bigint em vez do tipo de caractere.

É irrealista esperar que ele obtenha o tipo de coluna correto? Estou usando errado ou tenho as expectativas erradas? Espera -se que eu tenha que usar a columnidade de seleção a cada vez?

Atualizar:Aqui estão as informações relevantes da entidade da organização

@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        
 }

E aqui está a entidade contratada

@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
}
Foi útil?

Solução

É irrealista esperar que ele obtenha o tipo de coluna correto?

Não, não é irrealista e o resultado atual é claramente inesperado.

Estou usando errado ou tenho as expectativas erradas?

Seus mapeamentos não parecem errados. Você poderia apenas tentar o seguinte e confirmar que obtenha o mesmo resultado (estou simplesmente omitindo o referencedColumnName que você não deveria ter que definir de qualquer maneira)?

@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;
    ...
}

Eu não tenho o PostgreSQL instalado, não posso tentar.

Espera -se que eu tenha que usar a columnidade de seleção a cada vez?

Não.

Outras dicas

Eu acredito que a questão é de sensibilidade ao caso.

Você não definiu um @column no atributo ID da chave, então o nome da coluna padrão é "chave". No seu @ManytoOne, você referenciou "Key", que não é a mesma coluna, então o Eclipselink (que é sensível ao caso e suporta referências de chave estrangeira não id) assumiu que essa era uma coluna diferente e que não conhecia, então deu é o tipo padrão de varchar.

Altere o nome referencedColumnName para "Key" ou remova -o, pois não é necessário ao fazer referência a um ID de singleton.

Vale a pena registrar um bug no Eclipselink de que um aviso deve ser registrado quando uma referência de coluna não for encontrada ou o caso errado (talvez até alterne o caso automaticamente). Na verdade, podemos já estar registrando um aviso, você pode verificar seu log.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top