Domanda

Ho una tabella che ha due chiavi esterne a due tavoli diversi con due chiavi esterne la condivisione di una colonna :

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)
)

Come si può vedere, ci sono due FKS condivisione country_code (guarda caso riferimento alla stessa colonna, alla fine del percorso di referenziazione). L'aspetto classe di entità come (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;

    ...
}

Come potete vedere ho segnalato la proprietà countryCode e country_code @JoinColumn città come di sola lettura (inseribile = false, aggiornabile = false). Hibernate riesce con questo dicendo:

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

Questo sembra piuttosto semplice per me onestamente. "Mixing colonne inseribili e non inseribili in una proprietà non è permesso" è come un debole "scusa", non è vero?

Qualora Sospensione essere in grado di gestire questo, ad esempio secondo la specifica JPA? Questo è un bug?

È stato utile?

Soluzione 2

Sarà sostenuto con Hibernate 5, vedi https://hibernate.atlassian.net/browse / HHH-6221

Altri suggerimenti

C'è un modo per aggirare la convalida e farlo funzionare, indicando in tal modo la colonna è un "@JoinColumnsOrFormulas" poi mettere la soluzione:

Errore:

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

Saluti,

Sto usando Hibernate 5 e ho ancora questo l'eccezione. Se si aggiunge inserto = "false", l'aggiornamento = "false" a un solo, si otterrà un'eccezione che indica che è misti colonne inseribili e non inseribili e che questo non è permesso. Questo è un problema che è già in tracker, ma sembra non essere risolto. Hibernate tiri AnnotationException sulla colonna utilizzata da più sovrapposte chiavi esterne

Nel nostro caso, questo significa che abbiamo migrato a EclipseLink, che in realtà è abbastanza facile dato che si principalmente necessario sostituire il persistence.xml e riscrivere il HSQL (Hibernate SQL) per JPQL (JPA SQL). Inoltre potrebbe essere necessario sostituire le strategie di denominazione personalizzato (Eclipse li chiama SessionCustomizer). Naturalmente potrebbe essere più difficile da fare se si utilizzano funzioni speciali di Hibernate come Hibernate Search ecc Ma nel nostro caso, abbiamo cercato di risolvere la sovrapposizione chiavi esterne per settimane, quando la migrazione ha preso solo ora alla fine.

Questa non è ancora risolto in Hibernate 5. Tuttavia, se uso @JoinColumnsOrFormulas ottengo ClassCastException. Aggiungendo insertable = false, updatable = false su tutte le colonne unirsi Ha risolto il problema:

Esempio:

@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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top