2009-09-12 15 views
19

Tengo un problema con mi modelo de dominio jpa. Solo estoy tratando de jugar con la herencia simple para la cual utilizo una simple clase base de Persona y una subclase de Cliente. De acuerdo con la documentación oficial (tanto, JPA y EclipseLink) solo necesito el atributo de ID/columna en la clase base. ¿Pero cuando ejecuto mis pruebas, siempre obtengo un error al decirme que el Cliente no tiene @Id?ID de demandas de herencia JPA en la subclase

Primero pensé que el problema radica en la visibilidad del atributo de identificación, porque era privado primero. Pero incluso después de que lo cambié por protegido (para que la subclase tenga acceso directo) no funciona.

Persona:

@Entity @Table(name="Persons") 
@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorColumn(name = "TYPE") 
public class Person { 

    @Id 
    @GeneratedValue 
    protected int id; 
    @Column(nullable = false) 
    protected String firstName; 
    @Column(nullable = false) 
    protected String lastName; 

cliente:

@Entity @Table(name = "Customers") 
@DiscriminatorValue("C") 
public class Customer extends Person { 

    //no id needed here 

Me estoy quedando sin ideas y recursos a la vista. Debería ser un problema bastante simple, pero simplemente no lo veo.

+0

Tengo un problema similar. Creo que está vinculado a Eclipse.My JBoss Developer Tools se queja de la falta de @Id en una entidad derivada, pero Maven la compila sin quejarse. – Mats

Respuesta

25

lo resolví yo mismo mediante la creación de un MappedSuperclass

@MappedSuperclass 
public abstract class EntityBase{ 
    @Id 
    @GeneratedValue 
    private int id; 

    ...setter/getter 
} 

Todas las entidades están heredando de esta clase. Todavía me pregunto por qué los tutoriales no mencionan esto, pero tal vez mejore con las implementaciones de JPA 2.

+2

+1. Creo que esta es la respuesta correcta a su pregunta específica. –

+0

Gracias por el comentario. Todavía no estaba seguro de eso. – lostiniceland

+1

Por ahora, el doc-oráculo menciona la notación "MappedSuperclass": https://docs.oracle.com/javaee/7/tutorial/doc/persistence-intro002.htm. Definitivamente es el camino correcto :) –

3

APP conoce dos formas diferentes de aplicar la herencia:

  • herencia de tablas Usuario
  • Mesa única herencia

Con la herencia simple tabla se necesita una columna discriminadora para distinguir entre las filas de la mesa.

Con la herencia de tablas unidas, cada clase obtiene su propia tabla por lo que no se necesita una columna de discriminador.

Creo que su problema es que ha mezclado los dos conceptos. Así que o bien:

  • definir las columnas de discriminador y usar `InheritanceType.SINGLE_TABLE` y No uso` @ Table` en subclases
  • o usar `InheritanceType.JOINED` pero no especificar la columna discriminadora y los valores!
+1

Lo probé, pero sigue siendo el mismo problema. Además, de acuerdo con http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Joined.2C_Multiple_Table_Inheritance, puede usar el discriminador – lostiniceland

4

Sé que esto es viejo, pero no obstante válido. Tuve el mismo problema. Sin embargo, @MappedSuperClass no es lo mismo que una tabla de herencia única. MappedSuperClass creará tablas separadas para cada una de las subclases (según tengo entendido)

No estoy seguro de por qué, pero cuando solo tengo una clase heredada no tuve problemas. Sin embargo, una vez que agregué el segundo y el tercero, recibí el mismo error. Cuando especifiqué la anotación @Id en la tabla secundaria, comenzó a funcionar nuevamente.

Mi diseño era simple, información de contacto para empresas, agentes y clientes.

Tabla

Padres:

... 
@Entity 
@Inheritance(strategy= InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="USER_TYPE", length=10, discriminatorType= DiscriminatorType.STRING) 
@Table(name="CONTACTS") 
public abstract class AbstractContact implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 
    @Column (length=10, nullable=false) 
    protected String mapType; 
    @Column (length=120, nullable=false) 
    protected String mapValue; 
... 

Agente Contactos

@Entity 
@DiscriminatorValue("Agent") 
public class AgentContact extends AbstractContact implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 
    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="USER_ID") 
    protected Agents agent; 
} 

empresa Contacto:

@Entity 
@DiscriminatorValue("Company") 
public class CompanyContact extends AbstractContact implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 
    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="USER_ID") 
    protected Companies company; 

} 

cliente contacta con:

@Entity 
@DiscriminatorValue("Client") 
public class ClientContact extends AbstractContact implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 
    //Client table not built yet so... no mapping 
} 

La tabla de clientes aún no está construida, por lo que no hay información de mapeo, pero entiendes el punto.

¡Quisiera compartir la descripción de MySQL pero el símbolo del sistema de Windows es demasiado inútil para cortar/copiar/pegar! En esencia, su: ID (int PRI) USER_TYPE (VARCHAR (10)) USER_ID (INT) MapType (VARCHAR (10)) MAPVALUE (VARCHAR (120))

todavía tengo para configurar todos las pruebas, pero hasta ahora se ve bien (me temo que si espero hasta después de hacer todas las pruebas me olvidaré de publicar esto)

9

Tenía exactamente el mismo problema. Para subclase que estaba recibiendo:

Entity class [...] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass.

En mi caso resultó que se me olvidó añadir mi clase raíz en persistence.xml.

asegurarse de que usted tiene tanto la persona como cliente definen en:

<persistence> 
    <persistence-unit> 
    ... 
    <class>package.Person</class> 
    <class>package.Customer</class> 
    ... 
    </persistence-unit> 
</persistence> 
0

Puede haber otra razón para este error al utilizar Glassfish/EclipseLink: EclipseLink < 2.6.0 tiene un nasty bug clases causando con expresiones lambda en ella para ser ignorado. Esto puede generar errores confusos, como el que se menciona aquí, u otros errores similares (por ejemplo, EclipseLink puede decirle que una clase con una anotación @Entity no es una entidad).

Glassfish 4.1 incluye EclipseLink 2.5.x, por lo que este error (y muchos otros) te morderán si usas Glassfish. Estaba usando esta versión en lugar de 4.1.1 debido a otro error que imposibilitó la validación en los servicios web REST. Manténgase lo más lejos posible de Glassfish si desea mantener su cordura.

0

Puede obtener este tipo de error cuando no está generando el esquema de base de datos basado en sus entidades. Si ese es el caso:

primero - Su superclase siempre debe tener un @Id

segundo - Tu subclase debe tener alguna columna que identifica la clase extendida (super clase @Id)

tercero - La solución más simple para el caso presentado más arriba sería agregar una identificación de columna a la tabla de subclase, con la restricción de clave externa correspondiente.

Espero que esto ayude a alguien! ¡Pulgares arriba!

Cuestiones relacionadas