Por que o JPA escolhe a string para juncolumn, independentemente dos tipos de chave?
-
25-09-2019 - |
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
}
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.