Pregunta

Tengo una tabla que tiene dos claves ajenas a dos tablas diferentes con ambas claves externas compartir una columna

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 se puede ver, hay dos FKs compartiendo country_code (casualmente hace referencia a la misma columna al final de la ruta de referenciación). Las miradas de la clase de entidad como (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 se puede ver que la propiedad countryCode marcado y @JoinColumn country_code ciudad como de sólo lectura (insertable = false, actualizable = false). Hibernate falla con este dicho:

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

Esto parece bastante básico para mí, honestamente. "No está permitido Mezcla columnas insertables y no insertables en una propiedad" es un débil "excusa" tal, no es?

debería Hibernate ser capaz de manejar esto, por ejemplo, de acuerdo con la especificación JPA? Es esto un error?

¿Fue útil?

Solución 2

será apoyado con Hibernate 5, consulte https://hibernate.atlassian.net/browse / HHH-6221

Otros consejos

Hay una manera de evitar la validación y conseguir que funcione, lo cual indica que la columna es un "@JoinColumnsOrFormulas" a continuación, poner la solución:

Error:

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

Aceptar:

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

Saludos,

Estoy usando Hibernate 5 y sigo teniendo presente la excepción. Si se agrega inserto = "false", la actualización = "false" sólo a una, obtendrá una excepción que indique que usted columnas insertables y no insertables mixtos y que esto no está permitido. Este es un tema que ya está en el rastreador, pero no parece estar resuelto. Hibernate tiros AnnotationException en la columna utilizada por varias claves externas superpuestas

En nuestro caso, esto significa que migramos a EclipseLink, que en realidad es bastante fácil considerando que se necesita principalmente para reemplazar el persistence.xml y reescribir el HSQL (Hibernate SQL) para JPQL (APP SQL). También es posible que tenga que reemplazar las estrategias de asignación de nombres a medida (Eclipse SessionCustomizer los llama). Por supuesto que podría ser más difícil de hacer si utiliza características especiales de hibernación como hibernación de búsqueda, etc. Sin embargo, en nuestro caso, hemos tratado de corregir la superposición de las claves externas de semana cuando la migración sólo tomó horas al final.

Esto todavía no se soluciona en Hibernate 5. Sin embargo, si uso @JoinColumnsOrFormulas consigo ClassCastException. Al añadir insertable = false, updatable = false en todas las columnas de combinación resuelto mi problema:

Ejemplo:

@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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top