Hibernate lanza org.hibernate.AnnotationException: no se ha especificado un identificador para la entidad: com..domain.idea.MAE_MFEView

207

¿Por qué recibo esta excepción?

package com.domain.idea;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.AccessType;

/**
 * object model for the view [InvestmentReturn].[vMAE_MFE]
 */
@Entity
@Table(name="vMAE_MFE", schema="InvestmentReturn")
@AccessType("field")
public class MAE_MFEView
{
    /**
     * trade property is a SuggestdTradeRecommendation object
     */
    @OneToOne(fetch = FetchType.LAZY , cascade = { CascadeType.PERSIST })
    @JoinColumn(name = "suggestedTradeRecommendationID")
    private SuggestedTradeRecommendation trade;

    /**
     * Most Adeverse Excursion value
     */
    private int MAE;

    public int getMAE()
    {
        return MAE;
    }

    /**
     * Most Favorable Excursion value
     */
    private int MFE;

    public int getMFE()
    {
        return MFE;
    }

    /**
     * @return trade property
     * see #trade
     */
    public SuggestedTradeRecommendation getTrade()
    {
        return trade;
    }
}

Actualización: he cambiado mi código para que se vea así:

package com.domain.idea;

import javax.persistence.CascadeType;
import javax.persistence.FetchType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.AccessType;

/**
 * object model for the view [InvestmentReturn].[vMAE_MFE]
 */
@Entity
@Table(name="vMAE_MFE", schema="InvestmentReturn")
@AccessType("field")
public class MAE_MFEView
{
    /**
     * trade property is a SuggestdTradeRecommendation object
     */
    @Id
    @OneToOne(fetch = FetchType.LAZY , cascade = { CascadeType.PERSIST })
    @JoinColumn(name = "suggestedTradeRecommendationID")
    private SuggestedTradeRecommendation trade;

    /**
     * Most Adeverse Excursion value
     */
    private int MAE;

    public int getMAE()
    {
        return MAE;
    }

    /**
     * Most Favorable Excursion value
     */
    private int MFE;

    public int getMFE()
    {
        return MFE;
    }

    /**
     * @return trade property
     * see #trade
     */
    public SuggestedTradeRecommendation getTrade()
    {
        return trade;
    }
}

pero ahora recibo esta excepción:

Caused by: org.hibernate.MappingException: Could not determine type for: com.domain.idea.SuggestedTradeRecommendation, at table: vMAE_MFE, for columns: [org.hibernate.mapping.Column(trade)]
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:292)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:276)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:216)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1135)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1320)
    at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669)
    ... 145 more
Ramy
fuente
por cierto, sin relación con la pregunta, esa es una traza de pila bastante larga. Tienes algunas invocaciones repetidas. ¿Estás seguro de que todo está correcto allí?
Bozho
No estoy muy seguro de por qué los rastros de la pila son siempre tan largos. Creo que hay muchos servicios en segundo plano en ejecución que se ven afectados.
Ramy
Presta atención si tu identificación no es estática o algunos atributos en tu clase. Sucedió conmigo :)
Gean Felipe

Respuestas:

434

Te falta un campo anotado con @Id. Cada uno @Entitynecesita un @Id: esta es la clave principal en la base de datos.

Si no desea que su entidad sea persistente en una tabla separada, sino que sea parte de otras entidades, puede usarla en @Embeddablelugar de @Entity.

Si desea simplemente que un objeto de transferencia de datos contenga algunos datos de la entidad de hibernación, no use anotaciones en absoluto, déjelo como un simple pojo.

Actualización: en lo que respecta a las vistas SQL, los documentos de Hibernate escriben:

No hay diferencia entre una vista y una tabla base para un mapeo de Hibernate. Esto es transparente a nivel de base de datos

Bozho
fuente
2
Tengo que tener un campo @Id? Mi punto de vista no tiene, estrictamente hablando, una identificación.
Ramy
¿Qué quieres decir con "vista"? No hay "vista" en Hibernate. Solo hay modelo.
Bozho
1
bueno, asigne alguna identificación a la vista. No puedo ir sin eso. Cada fila (objeto) tiene que identificarse de manera única.
Bozho
obteniendo una nueva excepción después de agregar @Id
Ramy
3
¡Gracias! ¡Esto solucionó un molesto NullPointerFromHellException!
malix
172

Para mí, javax.persistence.Iddebería usarse en lugar de org.springframework.data.annotation.Id. Para cualquiera que haya encontrado este problema, puede verificar si importó la Idclase correcta .

Searene
fuente
2
Me salvaste el día: ')
Amitrajit Bose
Tuve un problema similar.
AngelThread
59

Este error puede ser arrojado al importar una biblioteca diferente para @Id que Javax.persistance.Id ; Es posible que también deba prestar atención a este caso

En mi caso tuve

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Table;

import org.springframework.data.annotation.Id;

@Entity
public class Status {

    @Id
    @GeneratedValue
    private int id;

cuando cambio el código de esta manera, funcionó

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Table;

import javax.persistence.Id;

@Entity
public class Status {

    @Id
    @GeneratedValue
    private int id;
Tadele Ayelegn
fuente
1
consejos valiosos ... desaprobar org.springframework.data.annotation.Id plz
Christian Meyer
13

El siguiente código puede resolver la NullPointerException.

@Id
@GeneratedValue
@Column(name = "STOCK_ID", unique = true, nullable = false)
public Integer getStockId() {
    return this.stockId;
}
public void setStockId(Integer stockId) {
    this.stockId = stockId;
}

Si agrega @Id, puede declarar algunos más como el método declarado anteriormente.

Shivendra Prakash Shukla
fuente
becoz su valor de @Id no se asignó y actualizó en ningún lugar donde haya una excepción de puntero nulo ...
Shivendra Prakash Shukla
2

Sé que suena loco pero recibí ese error porque olvido eliminar

private static final long serialVersionUID = 1L;

generado automáticamente por la herramienta Eclipse JPA cuando se realiza una transformación de tabla a entidades.

Eliminando la línea de arriba que resolvió el problema

ittradco
fuente
1

El uso de @EmbeddableId para la entidad PK ha resuelto mi problema.

@Entity
@Table(name="SAMPLE")
 public class SampleEntity implements Serializable{
   private static final long serialVersionUID = 1L;

   @EmbeddedId
   SampleEntityPK id;

 }
Venkatesh Ramoju
fuente
1

Creo que este problema después de la clase de modelo de importación incorrecta.

    import org.springframework.data.annotation.Id;

Normalmente, debería ser:

    import javax.persistence.Id;
Mahendra Sri
fuente
1

TL; DR

Te falta la @Idpropiedad de la entidad, y es por eso que Hibernate está lanzando esa excepción.

Identificadores de entidad

Cualquier entidad JPA debe tener una propiedad de identificador, que está marcada con la Idanotación.

Hay dos tipos de identificadores:

  • asignado
  • auto generado

Identificadores asignados

Un identificador asignado tiene el siguiente aspecto:

@Id
private Long id;

Tenga en cuenta que estamos utilizando una envoltura (por ejemplo, Long, Integer) en lugar de un tipo primitivo (por ejemplo, long, int). Usar un tipo de contenedor es una mejor opción cuando se usa Hibernate porque, al verificar si ides nullo no, Hibernate puede determinar mejor si una entidad es transitoria (no tiene una fila de tabla asociada) o separada (tiene una fila de tabla asociada, pero no está gestionado por el contexto de persistencia actual).

El identificador asignado debe ser configurado manualmente por la aplicación antes de que la llamada persista:

Post post = new Post();
post.setId(1L);

entityManager.persist(post);

Identificadores autogenerados

Un identificador autogenerado requiere la @GeneratedValueanotación además de @Id:

@Id
@GeneratedValue
private int id;

Como expliqué en este artículo , hay 3 estrategias que Hibernate puede usar para generar automáticamente el identificador de entidad:

  • IDENTITY
  • SEQUENCE
  • TABLE

La IDENTITYestrategia debe evitarse si la base de datos subyacente admite secuencias (por ejemplo, Oracle, PostgreSQL, MariaDB desde 10.3 , SQL Server desde 2012). La única base de datos importante que no admite secuencias es MySQL.

El problema IDENTITYes que las inserciones automáticas de lotes de Hibernate están deshabilitadas para esta estrategia. Para obtener más detalles sobre este tema, consulte este artículo .

La SEQUENCEestrategia es la mejor opción a menos que esté usando MySQL. Para la SEQUENCEestrategia, también desea utilizar el pooledoptimizador para reducir el número de viajes de ida y vuelta de la base de datos al persistir varias entidades en el mismo contexto de persistencia.

El TABLEgenerador es una elección terrible porque no escala . Para la portabilidad, es mejor usarlo SEQUENCEde forma predeterminada y cambiar a IDENTITYMySQL solamente, como se explica en este artículo .

Vlad Mihalcea
fuente
El primer ejemplo no debería tener @GeneratedValue, ¿verdad?
Josef Cech
0

Este error fue causado al importar la clase de Id incorrecta. Después de cambiar org.springframework.data.annotation.Id a javax.persistence.Id, la aplicación se ejecuta

Philip Afemikhe
fuente