Hibernacja wyrzuca org.hibernate.AnnotationException: Nie określono identyfikatora encji: com..domain.idea.MAE_MFEView

207

Dlaczego otrzymuję ten wyjątek?

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

Aktualizacja: Zmieniłem kod, aby wyglądał następująco:

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

ale teraz otrzymuję ten wyjątek:

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
źródło
btw, niezwiązane z pytaniem, to dość długi ślad stosu. Masz kilka powtarzających się inwokacji. Czy jesteś pewien, że wszystko tam jest poprawne?
Bozho,
nie jestem pewien, dlaczego ślady stosu są zawsze tak długie. Myślę, że ma to wpływ na wiele usług w tle.
Ramy
Zwróć uwagę, jeśli twój identyfikator nie jest statyczny lub jakieś atrybuty w twojej klasie. Stało się to ze mną :)
Gean Felipe,

Odpowiedzi:

433

Brakuje pola z adnotacją @Id. Każdy @Entitypotrzebuje @Id- jest to klucz podstawowy w bazie danych.

Jeśli nie chcesz, aby twoja jednostka była utrwalona w osobnej tabeli, ale raczej była częścią innych jednostek, możesz użyć @Embeddablezamiast niej @Entity.

Jeśli chcesz, aby po prostu obiekt do przesyłania danych przechowywał niektóre dane z hibernacji, nie używaj do niego adnotacji - zostaw to proste pojęcie.

Aktualizacja: W odniesieniu do widoków SQL dokumenty Hibernacja piszą:

Nie ma różnicy między widokiem a tabelą podstawową dla mapowania Hibernacja. Jest to przejrzyste na poziomie bazy danych

Bozho
źródło
2
Muszę mieć pole @Id? Mój pogląd nie ma, ściśle mówiąc, dokumentu tożsamości.
Ramy
Co masz na myśli „widok”. W Hibernacji nie ma „widoku”. Jest tylko model.
Bozho,
1
przypisz jakiś identyfikator do widoku. Nie da się bez tego obejść. Każdy wiersz (obiekt) musi być jednoznacznie zidentyfikowany.
Bozho,
uzyskiwanie nowego wyjątku po dodaniu @Id
Ramy
3
Dziękuję Ci! To naprawiło irytujący wyjątek NullPointerFromHellException!
malix
172

Dla mnie javax.persistence.Idnależy użyć zamiast org.springframework.data.annotation.Id. Dla każdego, kto napotkał ten problem, możesz sprawdzić, czy zaimportowałeś odpowiednią Idklasę.

Searene
źródło
2
Uratowałeś mi dzień: ')
Amitrajit Bose
miał podobny problem.
AngelThread
59

Ten błąd może zostać zgłoszony podczas importowania innej biblioteki dla @Id niż Javax.persistance.Id ; Być może trzeba będzie zwrócić uwagę również na tę sprawę

W moim przypadku miałem

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;

kiedy zmieniam kod w ten sposób, działa

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
źródło
1
cenna rada .. przestarzałe org.springframework.data.annotation.Id plz
Christian Meyer
13

Poniższy kod może rozwiązać wyjątek 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;
}

Jeśli dodasz @Id, możesz zadeklarować trochę więcej jak wyżej zadeklarowana metoda.

Shivendra Prakash Shukla
źródło
ponieważ wartość ur @Id nie przypisała i nie zaktualizowała nigdzie, gdzie nie ma wyjątku zerowego wskaźnika ...
Shivendra Prakash Shukla,
2

Wiem, że to szalone, ale otrzymałem taki błąd, ponieważ zapomniałem usunąć

private static final long serialVersionUID = 1L;

automatycznie generowane przez narzędzie JPA Eclipse, gdy dokonałem transformacji tabeli do encji.

Usunięcie powyższej linii rozwiązało problem

ittradco
źródło
1

Użycie @EmbeddableId dla jednostki PK rozwiązało mój problem.

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

   @EmbeddedId
   SampleEntityPK id;

 }
Venkatesh Ramoju
źródło
1

Myślę, że ten problem wynika z nieprawidłowego importu klasy modelu.

    import org.springframework.data.annotation.Id;

Zwykle powinno to być:

    import javax.persistence.Id;
Mahendra Sri
źródło
1

TL; DR

Brakuje @Idwłaściwości bytu i dlatego Hibernacja zgłasza ten wyjątek.

Identyfikatory jednostki

Każda jednostka JPA musi mieć właściwość identyfikatora oznaczoną Idadnotacją.

Istnieją dwa rodzaje identyfikatorów:

  • przydzielony
  • generowane automatycznie

Przypisane identyfikatory

Przypisany identyfikator wygląda następująco:

@Id
private Long id;

Zauważ, że używamy otoki (np. Long, Integer) Zamiast typu pierwotnego (np. long, int). Użycie typu opakowania jest lepszym wyborem podczas używania Hibernacji, ponieważ sprawdzając, czy idjest, nullczy nie, Hibernacja może lepiej określić, czy jednostka jest przejściowa (nie ma powiązanego wiersza tabeli), czy jest odłączona (ma powiązany wiersz tabeli, ale nie jest zarządzany przez bieżący kontekst trwałości).

Przypisany identyfikator musi być ustawiony ręcznie przez aplikację przed wywołaniem trwałego:

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

entityManager.persist(post);

Automatycznie wygenerowane identyfikatory

Automatycznie wygenerowany identyfikator wymaga @GeneratedValueadnotacji oprócz @Id:

@Id
@GeneratedValue
private int id;

Jak wyjaśniłem w tym artykule , istnieją 3 strategie, których Hibernacja może użyć do automatycznego wygenerowania identyfikatora jednostki:

  • IDENTITY
  • SEQUENCE
  • TABLE

IDENTITYStrategia należy unikać, jeśli podstawowa baza danych obsługuje sekwencje (np, Oracle, PostgreSQL, MariaDB od 10.3 , SQL Server od 2012 roku). Jedyną dużą bazą danych, która nie obsługuje sekwencji, jest MySQL.

Problem IDENTITYpolega na tym, że automatyczne wstawki wsadowe hibernacji są wyłączone dla tej strategii. Więcej informacji na ten temat można znaleźć w tym artykule .

SEQUENCEStrategia jest najlepszym wyborem, chyba że używasz MySQL. W przypadku SEQUENCEstrategii chcesz również użyć pooledoptymalizatora, aby zmniejszyć liczbę objazdów bazy danych podczas utrwalania wielu jednostek w tym samym kontekście trwałości.

TABLEGenerator jest straszny wybór, ponieważ to nie skaluje . Jeśli chodzi o przenośność, lepiej jest używać SEQUENCEdomyślnie i przejść IDENTITYna MySQL, jak wyjaśniono w tym artykule .

Vlad Mihalcea
źródło
Pierwszy przykład nie powinien mieć @GeneratedValue, prawda?
Josef Cech
0

Ten błąd został spowodowany przez zaimportowanie niewłaściwej klasy Id. Po zmianie org.springframework.data.annotation.Id na javax.persistence.Id aplikacja zostanie uruchomiona

Philip Afemikhe
źródło