Hibernate genera org.hibernate.AnnotationException: nessun identificativo specificato per l'entità: com..domain.idea.MAE_MFEView


207

Perché ricevo questa eccezione?

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;
    }
}

Aggiornamento: ho modificato il mio codice in questo modo:

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;
    }
}

ma ora sto ricevendo questa eccezione:

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

tra l'altro, non correlato alla domanda, questa è una traccia stack piuttosto lunga. Hai delle invocazioni ripetute. Sei sicuro che tutto sia corretto lì.
Bozho,

non sono troppo sicuro del perché le tracce dello stack siano sempre così lunghe. Penso che ci siano molti servizi in background che sono interessati.
Ramy,

Fai attenzione se il tuo ID non è statico o alcuni attributi nella tua classe. È successo con me :)
Gean Felipe il

Risposte:


434

Manca un campo annotato con @Id. Ognuno ha @Entitybisogno di un @Id: questa è la chiave primaria nel database.

Se non vuoi che la tua entità sia mantenuta in una tabella separata, ma piuttosto faccia parte di altre entità, puoi usare @Embeddableinvece di @Entity.

Se si desidera semplicemente che un oggetto di trasferimento dati contenga alcuni dati dall'entità ibernata, non utilizzare alcuna annotazione su di esso - lasciarlo un semplice cursore.

Aggiornamento: per quanto riguarda le viste SQL, i documenti di Hibernate scrivono:

Non vi è alcuna differenza tra una vista e una tabella di base per un mapping Hibernate. Questo è trasparente a livello di database


2
Devo avere un campo @Id? La mia opinione non ha, in senso stretto, un documento d'identità.
Ramy,

Cosa intendi con "vista". Non esiste una "vista" a Hibernate. C'è solo un modello.
Bozho,

1
bene, assegna qualche id alla vista. Non posso farne a meno. Ogni riga (oggetto) deve essere identificata in modo univoco.
Bozho,

ottenere una nuova eccezione dopo aver aggiunto @Id
Ramy il

3
Grazie! Questo risolto un fastidioso NullPointerFromHellException!
malix,

172

Per me, javax.persistence.Iddovrebbe essere usato al posto di org.springframework.data.annotation.Id. Per chiunque abbia riscontrato questo problema, puoi verificare se hai importato la Idclasse giusta .


2
Mi hai salvato la giornata: ')
Amitrajit Bose il

ha avuto un problema simile.
AngelThread

59

Questo errore può essere generato quando si importa una libreria diversa per @Id rispetto a Javax.persistance.Id ; Potrebbe essere necessario prestare attenzione anche a questo caso

Nel mio caso l'ho avuto

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;

quando cambio il codice in questo modo, ha funzionato

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;

1
prezioso consiglio .. deprecate org.springframework.data.annotation.Id plz
Christian Meyer

13

Il codice seguente può risolvere 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;
}

Se aggiungi @Id, puoi dichiararne altri come il metodo sopra dichiarato.


perché il valore @Id non è stato assegnato e non è stato aggiornato da nessuna parte che abbia un'eccezione puntatore null ...
Shivendra Prakash Shukla,

2

So che sembra pazzo ma ho ricevuto un errore del genere perché ho dimenticato di rimuovere

private static final long serialVersionUID = 1L;

generato automaticamente dallo strumento Eclipse JPA quando ho fatto una trasformazione da tabella a entità.

Rimozione della riga sopra che ha risolto il problema


1

L'uso di @EmbeddableId per l'entità PK ha risolto il mio problema.

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

   @EmbeddedId
   SampleEntityPK id;

 }

1

Penso che questo problema a seguito dell'importazione errata della classe del modello.

    import org.springframework.data.annotation.Id;

Normalmente, dovrebbe essere:

    import javax.persistence.Id;

1

TL; DR

Ti manca il @Id proprietà dell'entità ed è per questo che Hibernate sta lanciando tale eccezione.

Identificatori di entità

Qualsiasi entità JPA deve avere una proprietà identificatore, contrassegnata con Id annotazione.

Esistono due tipi di identificatori:

  • assegnato
  • generato automaticamente

Identificatori assegnati

Un identificatore assegnato ha il seguente aspetto:

@Id
private Long id;

Si noti che stiamo usando un involucro (ad esempio Long, Integer) invece di un tipo primitivo (ad esempio, long, int). L'uso di un tipo di wrapper è una scelta migliore quando si utilizza Hibernate perché, controllando se lo idè nullo no, Hibernate può determinare meglio se un'entità è transitoria (non ha una riga di tabella associata) o staccata (ha una riga di tabella associata, ma non è gestito dall'attuale contesto di persistenza).

L'identificatore assegnato deve essere impostato manualmente dall'applicazione prima di chiamare persist:

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

entityManager.persist(post);

Identificatori generati automaticamente

Un identificatore generato automaticamente richiede l' @GeneratedValueannotazione oltre a @Id:

@Id
@GeneratedValue
private int id;

Come ho spiegato in questo articolo , ci sono 3 strategie che Hibernate può utilizzare per generare automaticamente l'identificatore di entità:

  • IDENTITY
  • SEQUENCE
  • TABLE

La IDENTITYstrategia deve essere evitata se il database sottostante supporta sequenze (ad es. Oracle, PostgreSQL, MariaDB dal 10.3 , SQL Server dal 2012). L'unico database principale che non supporta le sequenze è MySQL.

Il problema IDENTITYè che gli inserimenti batch automatici Hibernate sono disabilitati per questa strategia. Per maggiori dettagli su questo argomento, consulta questo articolo .

La SEQUENCEstrategia è la scelta migliore se non si utilizza MySQL. Per la SEQUENCEstrategia, si desidera anche utilizzare l' pooledottimizzatore per ridurre il numero di roundtrip del database quando si persistono più entità nello stesso contesto di persistenza.

Il TABLEgeneratore è una scelta terribile perché non si ridimensiona . Per la portabilità, è meglio usare SEQUENCEdi default e passare a IDENTITYsolo per MySQL, come spiegato in questo articolo .


Il primo esempio non dovrebbe avere @GeneratedValue, giusto?
Josef Cech

0

Questo errore è stato causato dall'importazione della classe Id errata. Dopo aver modificato org.springframework.data.annotation.Id in javax.persistence.Id dell'applicazione eseguita

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.