2009-05-27 14 views
75

com.something.SuperClass:No se puede utilizar la columna de identidad con la generación de claves <union-subclass> (TABLE_PER_CLASS)

@Entity 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public abstract class SuperClass implements Serializable { 
    private static final long serialVersionUID = -695503064509648117L; 

    long confirmationCode; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) // Causes exception!!! 
    public long getConfirmationCode() { 
     return confirmationCode; 
    } 

    public void setConfirmationCode(long confirmationCode) { 
     this.confirmationCode = confirmationCode; 
    } 
} 

com.something.SubClass:

@Entity 
public abstract class Subclass extends SuperClass { 
    private static final long serialVersionUID = 8623159397061057722L; 

    String name; 

    @Column(nullable = false) 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

Da esta excepción:

Caused by: org.hibernate.MappingException: Cannot use identity column key 
generation with <union-subclass> mapping for: com.something.SuperClass 

¿Cuál es la mejor y más conveniente forma de generar los ID? No quiero cambiar mi estrategia de herencia.

Respuesta

190

El problema aquí es que se mezcla la herencia "tabla por clase" y GenerationType.Auto. Considere una columna de identidad en MsSQL. Está basado en columnas. En una estrategia de "tabla por clase", utiliza una tabla por clase y cada una tiene una ID.

Probar:

@GeneratedValue(strategy = GenerationType.TABLE)

+1

Solución perfecta. Incluso los foros Hibernate didnot parecen tener esta solución, y que iban en torno al tema https://forum.hibernate.org/viewtopic.php?p=2319244&sid=4493aa54d27d3f81a0e27ecbdda075ae –

+1

¿Este problema es con MySql única o su regularidad como veo uno de un video para la tabla por enfoque de clase y estaba funcionando bien en que se usó postgres – Prashant

+1

Me encontré con esto recientemente cuando probaba una aplicación Dropwizard. En mi caso, lo resolví asegurándome de usar las mismas opciones de configuración utilizadas por DW para crear la fábrica de sesiones. Estoy bastante seguro de que establecer la propiedad "hibernate.id.new_generator_mappings" en true es lo que lo solucionó. Esto es DW 0.7.0, Hibernate 4.3.1, DB era H2. – sfitts

6

Me pregunto si esto es un problema específico dialecto de base de datos, ya que ver un tutorial de youtube con PostgreSQL como base de datos subyacente vi que el creador del video plazo succefully una aplicación con el valor predeterminado @GeneratedValue. En mi caso (la base de datos subyacente es MySQL) tuve que modificar la estrategia @GeneratedValue a GenerationType.TABLE exactamente como lo propone zoidbeck.

aquí está el vídeo: https://www.youtube.com/watch?v=qIdM4KQOtH8

+0

Postgres es capaz de hacer herencia por lo que puede tener razón de que esta es una base de datos específica: http://www.postgresql.org/docs/8.1 /static/ddl-inherit.html El video no explica (o lo perdí) cómo se genera el esquema. Así que tal vez el dialecto postgres de NHibernate pueda hacerlo solo o en su lugar, tenga que agregar 'INHERIDOS' manualmente. En realidad no puedo decirlo. – zoidbeck

+5

En PostgreSQL, Hibernate usa de forma predeterminada 'GenerationType.SEQUENCE'. Es por eso que funciona automáticamente allí. No tiene absolutamente nada que ver con 'INHERIDOS' de PostgreSQL. – Henning

+0

he estado usando el mismo tutorial y el uso de @Generated estaba causando problema ya que estoy usando MySql.Pastí mucho tiempo depurando hasta que vi esta publicación –

2

En nuestro caso, se utiliza una base de datos PostgreSQL para dev y producción y una base de datos en memoria hsqldb para las pruebas. Estamos usando una secuencia en ambos casos para generar una identificación. Aparentemente, GenerationType.AUTO está predeterminado en SEQUENCE para postgres, pero falló en nuestras pruebas locales (debe tener como valor predeterminado algo más para hsqldb).

Así que la solución que funcionó para nosotros, explícitamente use GenerationType.SEQUENCE.

-1

Hay un estándar SQL de cumplimiento entre MySQL y PostgreSQL. PostgreSQL Postgres entiende un buen subconjunto de SQL92/99 más algunas características orientadas a objetos para estos subconjuntos. Postgres es capaz de manejar rutinas y reglas complejas como consultas declarativas de SQL, subconsultas, vistas, soporte multiusuario, transacciones, optimización de consultas, herencia y matrices. No admite la selección de datos en diferentes bases de datos.

MySQL MySQL utiliza SQL92 como su base. Se ejecuta en innumerables plataformas. Mysql puede construir consultas que pueden unir tablas de diferentes bases de datos. Admite combinaciones externas izquierda y derecha usando sintaxis ANSI y ODBC. A partir de MySQL 4.1 desde esa versión, MySQL manejará las subconsultas. Vistas admitidas a partir del lanzamiento 5.

Para obtener una descripción detallada, visite. http://www-css.fnal.gov/dsg/external/freeware/pgsql-vs-mysql.html

+0

Por favor, no se sienta mal por esto, pero creo que la comparación de MySQL y PostgreSQL es irrelevante para el tema (a pesar de que los valores predeterminados de Hibernate son diferentes para ellos). – mrts

2

De acuerdo con la respuesta de zoidbeck. Es necesario un cambio de estrategia a:

@GeneratedValue(strategy = GenerationType.TABLE) 

Pero eso no es todo, es necesario crear una nueva tabla, lo que llevará a cabo la secuencia de clave principal de la tabla de su resumen. Modificar la asignación de

@Id 
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ConfirmationCodeGenerator") 
@TableGenerator(table = "SEQUENCES", name = "ConfirmationCodeGenerator") 
public long getConfirmationCode() { 
    return confirmationCode; 
} 

Y una nueva tabla en la base de datos debe ser similar a lo siguiente: enter image description here

Al ejecutar la aplicación, Hibernate insertará una fila en la que sequence_name será el nombre de la entidad (SuperClass en este ejemplo) y el valor sequence_next_hi_value se incrementará automáticamente y se usará para nuevos registros de todas las tablas de subclases implementadas.

0

puede usar @MappedSuperclass para la herencia

+0

¿podría agregar un código de ejemplo para su respuesta? –

Cuestiones relacionadas