Pergunta

Eu tenho uma tabela que possui duas chaves estrangeiras para duas tabelas diferentes com ambas as chaves estrangeiras compartilhando uma coluna:

CREATE TABLE ZipAreas
(
  country_code CHAR(2) NOT NULL,
  zip_code VARCHAR(10) NOT NULL,
  state_code VARCHAR(5) NOT NULL,
  city_name VARCHAR(100) NOT NULL,
  PRIMARY KEY (country_code, zip_code, state_code, city_name),
  FOREIGN KEY (country_code, zip_code) REFERENCES Zips (country_code, code),
  FOREIGN KEY (country_code, state_code, city_name) REFERENCES Cities (country_code, state_code, name)
)

Como você pode ver, existem dois FKs compartilhando country_code (referenciando coincidentemente a mesma coluna no final do caminho de referenciação).A classe de entidade se parece com (JPA 1.0 @IdClass):

@Entity
@Table(name = "ZipAreas")
@IdClass(value = ZipAreaId.class)
public class ZipArea implements Serializable
{
    @Id
    @Column(name = "country_code", insertable = false, updatable = false)
    private String countryCode;

    @Id
    @Column(name = "zip_code", insertable = false, updatable = false)
    private String zipCode;

    @Id
    @Column(name = "state_code", insertable = false, updatable = false)
    private String stateCode;

    @Id
    @Column(name = "city_name", insertable = false, updatable = false)
    private String cityName;

    @ManyToOne
    @JoinColumns(value = {@JoinColumn(name = "country_code", referencedColumnName = "country_code"), @JoinColumn(name = "zip_code", referencedColumnName = "code")})
    private Zip zip = null;

    @ManyToOne
    @JoinColumns(value = {@JoinColumn(name = "country_code", referencedColumnName = "country_code", insertable = false, updatable = false), @JoinColumn(name = "state_code", referencedColumnName = "state_code"), @JoinColumn(name = "city_name", referencedColumnName = "name")})
    private City city = null;

    ...
}

Como você pode ver, sinalizei a propriedade countryCode e o country_code @JoinColumn da cidade como somente leitura (inserível = falso, atualizável = falso).O Hibernate falha com este ditado:

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: geoinfo] Unable to configure EntityManagerFactory
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:374)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:56)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
    at tld.geoinfo.Main.main(Main.java:27)
Caused by: org.hibernate.AnnotationException: Mixing insertable and non insertable columns in a property is not allowed: tld.geoinfo.model.ZipAreacity
    at org.hibernate.cfg.Ejb3Column.checkPropertyConsistency(Ejb3Column.java:563)
    at org.hibernate.cfg.AnnotationBinder.bindManyToOne(AnnotationBinder.java:2703)
    at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1600)
    at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:796)
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:707)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3977)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3931)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1368)
    at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345)
    at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1477)
    at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193)
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1096)
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:278)
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:362)
    ... 4 more

Isso parece muito básico para mim, honestamente."Não é permitido misturar colunas inseríveis e não inseríveis em uma propriedade" é uma "desculpa" tão fraca, não é?

O Hibernate deve ser capaz de lidar com isso, por ex.de acordo com a especificação JPA?Isso é um inseto?

Foi útil?

Solução 2

Será apoiado com o Hibernate 5, ver https://hibernate.atlassian.net/browse/hhh-6221

Outras dicas

Existe uma maneira de ignorar a validação e fazê -lo funcionar, indicando assim que a coluna é um "@joincolumnSorformulas", em seguida, coloque a solução:

Erro:

@ManyToOne
@JoinColumns(value = {
    @JoinColumn(name = "country_code", referencedColumnName = "country_code"), 
    @JoinColumn(name = "zip_code", referencedColumnName = "code")})
private Zip zip = null;

@ManyToOne
@JoinColumns(value = {
    @JoinColumn(name = "country_code", referencedColumnName = "country_code", insertable = false, updatable = false),
    @JoinColumn(name = "state_code", referencedColumnName = "state_code"), 
    @JoinColumn(name = "city_name", referencedColumnName = "name")})
private City city = null;

OK:

@ManyToOne
@JoinColumns(value = {
    @JoinColumn(name = "country_code", referencedColumnName = "country_code"), 
    @JoinColumn(name = "zip_code", referencedColumnName = "code")})
private Zip zip = null;

@ManyToOne
@JoinColumnsOrFormulas(value = {
    @JoinColumnOrFormula(formula = @JoinFormula(value = "country_code", referencedColumnName = "country_code")),
    @JoinColumnOrFormula(column = @JoinColumn(name = "state_code", referencedColumnName = "state_code")),
    @JoinColumnOrFormula(column = @JoinColumn(name = "city_name", referencedColumnName = "name"))
})
private City city = null;

Cumprimentos,

Estou usando o hibernate 5 e ainda recebo essa exceção.Se você adicionar insert="false", update="false" apenas a uma, receberá uma exceção informando que misturou colunas inseríveis e não inseríveis e que isso não é permitido.Este é um problema que já está no rastreador, mas parece não estar resolvido. Hibernate lança AnnotationException na coluna usada por múltiplas chaves estrangeiras sobrepostas

No nosso caso, isso significou que migramos para o EclipseLink, o que na verdade é muito fácil, visto que você precisa principalmente substituir o persistence.xml e reescrever o HSQL (Hibernate SQL) para JPQL (JPA SQL).Além disso, pode ser necessário substituir estratégias de nomenclatura personalizadas (o Eclipse as chama de SessionCustomizer).É claro que pode ser mais difícil se você usar recursos especiais de hibernação, como pesquisa de hibernação, etc.Mas, no nosso caso, tentamos consertar chaves estrangeiras sobrepostas durante semanas, quando a migração levou apenas horas no final.

Isso ainda não está resolvido em Hibernate 5. No entanto, se eu usar @JoinColumnsOrFormulas Eu recebo ClassCastException. Anexando insertable = false, updatable = false Em todas as colunas de junção resolveram meu problema:

Exemplo:

@ManyToOne
@JoinColumns(value = {
    @JoinColumn(name = "country_code", referencedColumnName = "country_code", insertable = false, updatable = false),
    @JoinColumn(name = "state_code", referencedColumnName = "state_code", insertable = false, updatable = false), 
    @JoinColumn(name = "city_name", referencedColumnName = "name", insertable = false, updatable = false)})
private City city = null;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top