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
Рами
источник
Кстати, не имеет отношения к вопросу, это довольно длинная трассировка стека. У вас есть несколько повторяющихся заклинаний. Вы уверены, что там все правильно?
Божо
не слишком уверен, почему стековые трассировки всегда такие длинные. Я думаю, что есть много фоновых сервисов, которые работают.
Рами
Обратите внимание, если ваш идентификатор не является статичным или некоторые атрибуты в вашем классе. Это случилось со мной :)
Джан Фелипе

Ответы:

434

Вы пропустили поле с пометкой @Id. Каждому @Entityнужен @Id- это первичный ключ в базе данных.

Если вы не хотите, чтобы ваша сущность сохранялась в отдельной таблице, а была частью других сущностей, вы можете использовать @Embeddableвместо@Entity .

Если вы хотите, чтобы просто объект передачи данных содержал некоторые данные из спящего объекта, не используйте никаких аннотаций к нему - оставьте это простым pojo.

Обновление: Что касается представлений SQL, документы Hibernate пишут:

Нет никакой разницы между представлением и базовой таблицей для отображения Hibernate. Это прозрачно на уровне базы данных

Bozho
источник
2
У меня должно быть поле @Id? На мой взгляд, строго говоря, нет удостоверения личности.
Рами
Что вы имеете в виду «вид». В Hibernate нет «представления». Там только модель.
Божо
1
хорошо, назначьте некоторый идентификатор представлению. Не могу обойтись без этого. Каждая строка (объект) должна быть уникально идентифицирована.
Божо
получать новое исключение после добавления @Id
Рами
3
Спасибо! Это исправило раздражающее исключение NullPointerFromHellException!
Маликс
173

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

Searene
источник
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 плз
Кристиан Мейер
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 не присваивалось и не обновлялось нигде, у вас исключение нулевого указателя ...
Шивендра Пракаш Шукла
2

Я знаю, звучит безумно, но я получил такую ​​ошибку, потому что я забыл удалить

private static final long serialVersionUID = 1L;

автоматически генерируется инструментом Eclipse JPA при преобразовании таблицы в сущности.

Удаление строки выше, что решило проблему

ittradco
источник
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 может лучше определить, является ли объект переходным (у него нет связанной строки таблицы) или отделенным (у него есть связанная строка таблицы, но это не управляется текущим контекстом постоянства).

Присвоенный идентификатор должен быть установлен приложением вручную перед вызовом persist:

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

entityManager.persist(post);

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

Автоматически сгенерированный идентификатор требует @GeneratedValueаннотации помимо @Id:

@Id
@GeneratedValue
private int id;

Как я объяснил в этой статье , есть три стратегии, которые Hibernate может использовать для автоматической генерации идентификатора сущности:

  • IDENTITY
  • SEQUENCE
  • TABLE

IDENTITYСтратегии следует избегать , если основная база данных поддерживает последовательности (например, Oracle, PostgreSQL, MariaDB , так как 10.3 , SQL Server с 2012 года). Единственная основная база данных, которая не поддерживает последовательности, - это MySQL.

Проблема в IDENTITYтом, что автоматические пакетные вставки Hibernate отключены для этой стратегии. Для более подробной информации по этой теме, проверьте эту статью .

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

TABLEГенератор ужасный выбор , потому что это не масштаб . Для мобильности лучше использовать SEQUENCEпо умолчанию и переключаться только IDENTITYна MySQL, как описано в этой статье .

Влад Михалча
источник
Первый пример не должен иметь @GeneratedValue, верно?
Йозеф Чех
0

Эта ошибка была вызвана импортом неправильного класса Id. После изменения org.springframework.data.annotation.Id в javax.persistence. Идет запуск приложения.

Филипп Афемихе
источник