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
Ramy
fonte
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

Bozho
fonte
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 .

Searene
fonte
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;
Tadele Ayelegn
fonte
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.

Shivendra Prakash Shukla
fonte
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

ittradco
fonte
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;

 }
Venkatesh Ramoju
fonte
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;
Mahendra Sri
fonte
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 .

Vlad Mihalcea
fonte
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

Philip Afemikhe
fonte