Entidad JPA sin identificación

4 minutos de lectura

avatar de usuario
mijaíl

Tengo una base de datos con la siguiente estructura:

CREATE TABLE entity (
    id SERIAL,
    name VARCHAR(255),
    PRIMARY KEY (id)
);

CREATE TABLE entity_property (
    entity_id SERIAL,
    name VARCHAR(255),
    value TEXT
);

Cuando intento crear una clase EntityProperty

@Entity
@Table(name="entity_property")
public class EntityProperty {

    private String name;
    private String value;

    @Column(name="name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Column(name="value", nullable=true, length=255)
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
}

Obtengo la siguiente excepción:

org.hibernate.AnnotationException: No identifier specified for entity: package.EntityProperty

Sé que las entidades JPA deben tener una clave principal, pero no puedo cambiar el esquema de la base de datos por razones que escapan a mi control. ¿Es posible crear entidades JPA (Hibernate) que funcionen con un esquema de base de datos como este?

avatar de usuario
axtavt

supongo que tu entity_property tiene una clave compuesta (entity_id, name) donde entity_id es una clave foránea para entity. Si es así, puede mapearlo de la siguiente manera:

@Embeddable
public class EntityPropertyPK {
    @Column(name = "name")
    private String name;

    @ManyToOne
    @JoinColumn(name = "entity_id")
    private Entity entity;

    ...
}

@Entity 
@Table(name="entity_property") 
public class EntityProperty { 
    @EmbeddedId
    private EntityPropertyPK id;

    @Column(name = "value")
    private String value; 

    ...
}

  • Gracias. Pero, ¿cómo puedo acceder directamente a la propiedad “nombre” de la entidad en este caso? Mi consulta JP-QL funciona bien solo si se accede a “nombre” a través de “entity.id.name”, pero creo que no está bien.

    – mijaíl

    30 de septiembre de 2010 a las 6:23

  • @mikhail: Si no te gusta acércate con @EmbeddedIdpuede probar un enfoque alternativo con @IdClass: docs.jboss.org/hibernate/stable/annotations/reference/en/…

    – axtavt

    30 de septiembre de 2010 a las 9:10

  • Si la anotación para EntityPropertyPK ser @Embeddedable en lugar de @Embedded?

    – ensamblaje_binario

    9 de junio de 2015 a las 2:56


  • Sí, la anotación para EntityPropertyPK tiene que ser @Embeddable como @Embedded solo se puede aplicar en campos y métodos. Además, clase EntityPropertyPK debe declararse Serializable.

    – Dominick

    18/10/2016 a las 21:58

  • @mikhail: ¿podría mostrarme su mapeo dentro del archivo entidad.java?

    – Saravanan

    1 de noviembre de 2018 a las 6:30

Sé que las entidades JPA deben tener una clave principal, pero no puedo cambiar la estructura de la base de datos por razones que escapan a mi control.

Más precisamente, una entidad JPA debe tener algunos Id definido. Pero un JPA Id no necesariamente tiene que estar mapeado en la clave principal de la tabla (y JPA de alguna manera puede manejar una tabla sin una clave principal o restricción única).

¿Es posible crear entidades JPA (Hibernate) que funcionarán con una estructura de base de datos como esta?

Si tiene una columna o un conjunto de columnas en la tabla que genera un valor único, puede usar este conjunto único de columnas como su Id en JPA.

Si su tabla no tiene columnas únicas, puede usar todas las columnas como Id.

Y si su tabla tiene alguna identificación pero su entidad no, conviértala en una Embeddable.

  • por favor soy nuevo ¿Cómo puedo usar todas las columnas como ID en una entidad con este pequeño ejemplo: int SIN, int age, String name, String adresse? gracias

    –Omar B.

    9 noviembre 2018 a las 15:00


  • “puede usar todas las columnas como Id”, pero se requiere que mi tabla pueda almacenar filas idénticas como registros separados; c

    – Klesun

    14 de junio de 2021 a las 9:32

avatar de usuario
Gilberto

Ver el Persistencia de Java libro: Identidad y Secuencia

La parte relevante para su pregunta es la Sin sección de clave principal:

A veces, su objeto o tabla no tiene clave principal. La mejor solución en este caso es normalmente agregar una identificación generada al objeto y la tabla. Si no tiene esta opción, a veces hay una columna o un conjunto de columnas en la tabla que conforman un valor único. Puede usar este conjunto único de columnas como su identificación en JPA. La JPA Id
no siempre tiene que coincidir con la restricción de clave principal de la tabla de la base de datos, ni se requiere una clave principal o una restricción única.

Si su tabla realmente no tiene columnas únicas, use todas las columnas como ID. Por lo general, cuando esto ocurre, los datos son de solo lectura, por lo que incluso si la tabla permite filas duplicadas con los mismos valores, los objetos serán los mismos de todos modos, por lo que no importa que JPA piense que son el mismo objeto. El problema de permitir actualizaciones y eliminaciones es que no hay forma de identificar de forma única la fila del objeto, por lo que todas las filas coincidentes se actualizarán o eliminarán.

Si su objeto no tiene una identificación, pero su tabla sí, está bien. Convierte el objeto en un Embeddable object, los objetos incrustables no tienen id. necesitarás un Entity que contiene esto Embeddable para persistir y consultarlo.

Supongo que puedes usar @CollectionOfElements (para hibernar/jpa 1) / @ElementCollection (jpa 2) para mapear una colección de “propiedades de entidad” a un List en entity.

Puedes crear el EntityProperty escribe y anótalo con @Embeddable

Si hay un mapeo uno a uno entre entidad y entidad_propiedad, puede usar entidad_id como identificador.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad