2010-09-29 35 views
29

que tiene una base de datos con la siguiente estructura:entidad JPA sin Identificación

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

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

Cuando trato de 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; 
    } 
} 

me sale el 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 debido a razones que están más allá de mi cont Rol ¿Es posible crear entidades JPA (Hibernate) que funcionen con un esquema de base de datos como este?

Respuesta

32

Supongo que su entity_property tiene una clave compuesta (entity_id, name) donde entity_id es una clave externa al entity. Si es así, puede asignar 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; 

    ... 
} 
+1

Gracias. Pero, ¿cómo puedo acceder directamente a la propiedad de "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. – mikhail

+0

@mikhail: Si no le gusta el enfoque con '@ EmbeddedId', puede intentar un enfoque alternativo con' @ IdClass': http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e1112 – axtavt

+4

¿Debería la anotación para 'EntityPropertyPK' ser' @ Embeddedable' en lugar de '@ Embedded'? – HDoan

2

Creo que se puede utilizar @CollectionOfElements (por Hibernate/JPA 1)/@ElementCollection (JPA 2) para mapear una colección de "propiedades de la entidad" a un List en entity.

Puede crear el tipo EntityProperty y anotar con @Embeddable

0

Si hay una relación uno a uno entre entidad y entity_property puede utilizar entity_id como identificador.

22

sé que las entidades de la APP deben tener clave primaria pero no pueden cambiar la estructura de base de datos debido a razones fuera de mi control.

Más precisamente, una entidad JPA debe tener un poco de Id definido. Pero un JPA Id no necesariamente tiene que mapearse en la clave primaria de la tabla (y JPA de alguna manera puede tratar con una tabla sin una clave primaria o restricción única).

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

Si usted tiene una columna o un conjunto de columnas de la tabla que hace que un valor único, puede utilizar este conjunto único de columnas como su Id en APP.

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 lo tiene, hágala Embeddable.

10

Véase la persistencia de Java libro: Identity and Sequencing

La parte pertinente de tu pregunta es la No Primary Key section:

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

Si su tabla realmente no tiene columnas únicas, utilice todas las columnas como id. Normalmente, 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 JPA considera que son el mismo objeto. El problema con permitir actualizaciones y eliminaciones es que no hay forma de identificar de manera única la fila del objeto, por lo tanto, todas las filas coincidentes se actualizarán o eliminarán .

Si su objeto no tiene una identificación, pero su 'tabla lo hace, está bien. Haga que el objeto sea un objeto Embeddable, los objetos incrustados no tienen identificadores. Necesitará un Entity que contenga este Embeddable para persistir y consultarlo.

+0

Wow, eso fue súper perspicaz. Gracias por compartir. – comiventor

+0

Esto es lo que estaba buscando, ¡gracias! – lloiacono

Cuestiones relacionadas