O Hibernate lança org.hibernate.AnnotationException: nenhum identificador especificado para a entidade: com..domain.idea.MAE_MFEView


207

Por que estou recebendo essa exceção?

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

Atualização: alterei meu código para ficar assim:

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

mas agora estou recebendo essa exceção:

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

btw, não relacionado à pergunta, esse é um stacktrace bastante longo. Você tem algumas invocações repetidas. Você tem certeza de que tudo está correto lá?
— Bozho

não tenho certeza por que os rastreamentos de pilha são sempre tão longos. Eu acho que existem muitos serviços em segundo plano em execução que são afetados.
— Ramy

Preste atenção se seu ID não for estático ou se houver alguns atributos em sua classe. Foi o que aconteceu comigo :)
— Gean Felipe

Respostas:


434

Está faltando um campo anotado com @Id. Cada @Entityum precisa de @Id- esta é a chave primária no banco de dados.

Se você não deseja que sua entidade seja persistida em uma tabela separada, mas faça parte de outras entidades, você pode usar em @Embeddablevez de @Entity.

Se você deseja que simplesmente um objeto de transferência de dados retenha alguns dados da entidade de hibernação, não use anotações - deixe um simples pojo.

Atualização: Em relação às visualizações SQL, os documentos do Hibernate escrevem:

Não há diferença entre uma visualização e uma tabela base para um mapeamento do Hibernate. Isso é transparente no nível do banco de dados


2
Eu tenho que ter um campo @Id? Minha opinião não tem, estritamente falando, um ID.
— Ram10

O que você quer dizer com "ver". Não há "visualização" no Hibernate. Existe apenas modelo.
— Bozho

1
bem, atribua algum ID à visualização. Não pode ir sem ele. Cada linha (objeto) deve ser identificada exclusivamente.
— Bozho

recebendo uma nova exceção depois de adicionar @Id
— Ramy

3
Obrigado! Isso corrigiu um NullPointerFromHellException irritante!
— Malix 18/07

172

Para mim, javax.persistence.Iddeve ser usado em vez de org.springframework.data.annotation.Id. Para quem encontrou esse problema, você pode verificar se importou a Idclasse certa .


2
Você salvou meu dia: ')
— Amitrajit Bose 16/01

teve um problema semelhante.
— AngelThread 27/01

59

Este erro pode ser gerado quando você importa uma biblioteca diferente para @Id que Javax.persistance.Id ; Você pode precisar prestar atenção também neste caso

No meu caso eu tinha

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 eu mudo o código assim, funcionou

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
conselhos valiosos .. deprecate org.springframework.data.annotation.Id plz
— Christian Meyer

13

O código abaixo pode resolver a 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 você adicionar @Id, poderá declarar um pouco mais como o método declarado acima.


becoz ur valor @Id não fez qualquer lugar Atribuir & atualização que é u got exceção de ponteiro nulo ...
— Shivendra Prakash Shukla

2

Eu sei que parece loucura, mas recebi esse erro porque esqueci de remover

private static final long serialVersionUID = 1L;

gerado automaticamente pela ferramenta Eclipse JPA quando uma transformação de tabela em entidades que eu fiz.

Removendo a linha acima que resolveu o problema


1

O uso de @EmbeddableId para a entidade PK resolveu meu problema.

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

   @EmbeddedId
   SampleEntityPK id;

 }

1

Eu acho que esse problema após a importação errada da classe de modelo.

    import org.springframework.data.annotation.Id;

Normalmente, deve ser:

    import javax.persistence.Id;

1

TL; DR

Está faltando a @Idpropriedade da entidade, e é por isso que o Hibernate está lançando essa exceção.

Identificadores de entidade

Qualquer entidade JPA deve ter uma propriedade identificadora, marcada com a Idanotação.

Existem dois tipos de identificadores:

  • atribuído
  • Gerado automaticamente

Identificadores atribuídos

Um identificador atribuído é o seguinte:

@Id
private Long id;

Note-se que estamos a utilizar um dispositivo de moldagem (por exemplo, Long, Integer), em vez de um tipo primitivo (por exemplo, long, int). Usar um tipo de invólucro é uma opção melhor ao usar o Hibernate porque, ao verificar se idé nullou não, o Hibernate pode determinar melhor se uma entidade é transitória (não possui uma linha de tabela associada) ou desanexada (possui uma linha de tabela associada, mas não é gerenciado pelo atual contexto de persistência).

O identificador atribuído deve ser definido manualmente pelo aplicativo antes da chamada persistir:

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

entityManager.persist(post);

Identificadores gerados automaticamente

Um identificador gerado automaticamente requer a @GeneratedValueanotação além de @Id:

@Id
@GeneratedValue
private int id;

Como expliquei neste artigo , existem 3 estratégias que o Hibernate pode usar para gerar automaticamente o identificador de entidade:

  • IDENTITY
  • SEQUENCE
  • TABLE

A IDENTITYestratégia deve ser evitada se o banco de dados subjacente suportar sequências (por exemplo, Oracle, PostgreSQL, MariaDB desde 10.3 , SQL Server desde 2012). O único banco de dados importante que não suporta sequências é o MySQL.

O problema IDENTITYé que as inserções automáticas de lote do Hibernate estão desabilitadas para esta estratégia. Para mais detalhes sobre este tópico, consulte este artigo .

A SEQUENCEestratégia é a melhor opção, a menos que você esteja usando o MySQL. Para a SEQUENCEestratégia, você também deseja usar o pooledotimizador para reduzir o número de viagens de ida e volta ao banco de dados ao persistir várias entidades no mesmo Contexto de Persistência.

O TABLEgerador é uma escolha terrível, porque não é escalável . Para portabilidade, é melhor usar SEQUENCEpor padrão e alternar IDENTITYapenas para MySQL, conforme explicado neste artigo .


O primeiro exemplo não deveria ter @GeneratedValue, certo?
— Josef Cech

0

Este erro foi causado pela importação da classe de ID incorreta. Depois de alterar org.springframework.data.annotation.Id para javax.persistence.Id, o aplicativo é executado

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.