Hibernate кидає org.hibernate.AnnotationException: для сутності не вказаний ідентифікатор: com..domain.idea.MAE_MFEView


207

Чому я отримую цей виняток?

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

Оновлення: я змінив код, щоб виглядати так:

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

але зараз я отримую цей виняток:

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, не пов'язане з питанням, це досить довгий процес. У вас є кілька викликів, що повторюються. Ви впевнені, що там все правильно.
Божо

не надто впевнений, чому сліди стека завжди такі довгі. Я думаю, що існує багато фонових служб, які впливають.
Рамі

Зверніть увагу, якщо ваш ідентифікатор не є статичним або якісь атрибути у вашому класі. Це сталося зі мною :)
Геан Феліпе

Відповіді:


433

Вам не вистачає поля, в якому зазначається @Id. Кожен @Entityпотребує @Id- це первинний ключ у базі даних.

Якщо ви не хочете, щоб ваша сутність зберігалася в окремій таблиці, а скоріше була частиною інших сутностей, ви можете використовувати її @Embeddableзамість @Entity.

Якщо ви хочете просто об'єктом передачі даних зберігати деякі дані зі сплячого об'єкта, не використовуйте на ньому жодних анотацій - залиште це просте піхо.

Оновлення. Щодо переглядів SQL, документи зі сплячого режиму пишуть:

Немає різниці між поданням та базовою таблицею для відображення в сплячому режимі. Це прозоро на рівні бази даних


2
Я повинен мати поле @Id? Мій погляд, власне, не має посвідчення особи.
Рамі

Що означає «перегляд». У сплячому режимі немає «виду». Є тільки модель.
Божо

1
добре, призначте перегляд якийсь ідентифікатор. Не обійтися без цього. Кожен рядок (об’єкт) повинен бути однозначно ідентифікований.
Божо

отримувати нове виключення після додавання @Id
Рамі

3
Дякую! Це виправило дратує NullPointerFromHellException!
Малікс

172

Для мене javax.persistence.Idслід використовувати замість цього org.springframework.data.annotation.Id. Для всіх, хто стикався з цією проблемою, ви можете перевірити, чи імпортували ви правильний Idклас.


2
Ти врятував мій день: ')
Амітрадіт Босе

мали подібне питання.
AngelThread

59

Цю помилку можна видалити, коли ви імпортуєте іншу бібліотеку для @Id, ніж Javax.persistance.Id ; Можливо, вам доведеться звернути увагу і на цю справу

У моєму випадку я мав

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;

коли я змінюю такий код, він спрацював

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
цінна порада .. приниження org.springframework.data.annotation.Id plz
Christian Meyer

13

Нижче наведений код може вирішити 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;
}

Якщо ви додасте @Id, то ви можете оголосити ще кілька подібних способів, як описано вище.


becoz ur @Id значення не призначав і не оновлював ніде, що у вас є нульовим виключенням вказівника ...
Shivendra Prakash Shukla

2

Я знаю, що це звучить божевільно, але я отримав таку помилку, оскільки забув видалити

private static final long serialVersionUID = 1L;

автоматично генерується інструментом JPA Eclipse, коли я зробив перетворення таблиці на сутність.

Видалення рядка вище, який вирішив проблему


1

Використання @EmbeddableId для особи PK вирішило мою проблему.

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

   @EmbeddedId
   SampleEntityPK id;

 }

1

Я думаю, що ця проблема після модельного класу неправильний імпорт.

    import org.springframework.data.annotation.Id;

Зазвичай це повинно бути:

    import javax.persistence.Id;

1

TL; DR

Вам не вистачає @Idвластивості сутності, і саме тому Hibernate кидає цей виняток.

Ідентифікатори особи

Будь-яка організація JPA повинна мати властивість ідентифікатора, яка позначена Idанотацією.

Існує два типи ідентифікаторів:

  • призначений
  • автоматично генерується

Призначені ідентифікатори

Призначений ідентифікатор виглядає так:

@Id
private Long id;

Зверніть увагу , що ми використовуємо оболонку (наприклад, Long, Integer) , а НЕ примітивний тип (наприклад, long, int). Використання типу обгортки є кращим вибором при використанні Hibernate, оскільки, перевіривши, idє nullчи ні, Hibernate може краще визначити, чи є об'єкт тимчасовим (у нього немає пов'язаного рядка таблиці) чи відокремлений (у нього пов'язаний рядок таблиці, але це не керується поточним контекстом стійкості).

Призначений ідентифікатор повинен бути встановлений програмою вручну перед тим, як тривати виклик:

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

entityManager.persist(post);

Автоматично створені ідентифікатори

Автоматично створений ідентифікатор вимагає @GeneratedValueанотації окрім @Id:

@Id
@GeneratedValue
private int id;

Як я пояснив у цій статті , для автоматичного генерування ідентифікатора сутності можна використати 3 стратегії, які Hibernate може використовувати:

  • IDENTITY
  • SEQUENCE
  • TABLE

IDENTITYСтратегії слід уникати , якщо основна база даних підтримує послідовності (наприклад, Oracle, PostgreSQL, MariaDB , так як 10.3 , SQL Server з 2012 року). Єдина основна база даних, яка не підтримує послідовності, - MySQL.

Проблема IDENTITYполягає в тому, що для цієї стратегії вимкнено автоматичні пакетні вставки в сплячку. Детальніше про цю тему ознайомтеся з цією статтею .

SEQUENCEСтратегія є кращим вибором , якщо ви не використовуєте MySQL. Для SEQUENCEстратегії ви також хочете використовувати pooledоптимізатор, щоб зменшити кількість зворотних напрямків бази даних при збереженні декількох об'єктів в одному контенті персистенції.

TABLEГенератор жахливий вибір , тому що це не масштаб . Для портативності вам краще використовувати SEQUENCEза замовчуванням і перейти на IDENTITYлише для MySQL, як пояснено в цій статті .


Перший приклад не повинен мати @GeneratedValue, правда?
Йозеф Чех

0

Ця помилка була викликана імпортом неправильного класу Id. Після зміни org.springframework.data.annotation.Id на javax.persistence.Id додаток запускається

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.