Frage

Ich habe eine Tabelle, die zwei Fremdschlüssel zu zwei verschiedenen Tabellen mit den beiden Fremdschlüssel hat Austausch einer Spalte :

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

Wie Sie sehen können, gibt es zwei FKs teilen country_code (zufälligerweise sich auf die gleiche Spalte am Ende des referentiation Pfad). Die Entity-Klasse sieht aus wie (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;

    ...
}

Wie man sehen kann ich markiert die country Eigenschaft und country_code @JoinColumn der Stadt als Read-Only (einführbar = false, aktualisierbare = false). Hibernate Einzahler dieser sagen:

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

Das sieht ziemlich einfach für mich ehrlich. „Mischen einsetzbar und nicht einführbar Spalten in einer Eigenschaft ist nicht erlaubt“ ist so eine schwache „Entschuldigung“, ist es nicht?

Should Hibernate Lage sein, dies zu handhaben, zum Beispiel entsprechend der JPA spec? Ist das ein Fehler?

War es hilfreich?

Lösung 2

Wird mit Hibernate 5 unterstützt werden, finden Sie unter https://hibernate.atlassian.net/browse / HHH-6221

Andere Tipps

Es gibt einen Weg zur Umgehung der Validierung und bekommt es zu arbeiten, was darauf hindeutet, die Spalte ein „@JoinColumnsOrFormulas“ dann die Lösung setzen:

Fehler:

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

Grüße,

Ich verwende Hibernate 5 und ich dies immer noch die Ausnahme erhalten. Wenn Sie Insert = „false“ hinzufügen, aktualisieren = „false“ nur ein, erhalten Sie eine Ausnahme erhalten, dass Sie mischen einsetzbar und nicht einführbar Spalten und dass dies nicht erlaubt ist. Dies ist ein Thema, das bereits in dem Tracker ist, scheint aber nicht gelöst werden. Hibernate wirft AnnotationException auf Spalte von mehreren überlappenden Fremdschlüssel verwendet

In unserem Fall bedeutet dies, dass wir auf Eclipse migriert, die in der Tat recht einfach gegeben, dass Sie in erster Linie die persistence.xml ersetzen müssen und die HSQL (Hibernate SQL) zu JPQL (JPA SQL) umschreiben. Auch müssen Sie benutzerdefinierte Benennungsstrategien (Eklipse nennt sie SessionCustomizer) ersetzen. Natürlich könnte es schwieriger sein, wenn Sie spezielles Feature von Hibernate so verwenden zu tun, wie Hibernate usw. suchen, aber in unserem Fall haben wir versucht, sich überlappenden Fremdschlüssel für Wochen zu beheben, wenn die Migration nur wenig Stunden am Ende nahm.

Dies ist immer noch nicht in dem Ruhezustand 5 gelöst. Allerdings, wenn ich @JoinColumnsOrFormulas verwende ich Classcast bekommen. Anfügen insertable = false, updatable = false auf allen Joinspalten Hat mein Problem gelöst:

Beispiel:

@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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top