Автоматически сгенерированный идентификатор не каскадируется по EmbeddedId в дочерней сущности в Hibernate - PullRequest
1 голос
/ 18 мая 2019

При попытке вставить сущность - A с set, другая сущность B, B должна получить автоматически сгенерированный Id из A, но его null.

Попытка и ошибка:

  1. @MapsId("taskPKId.storyId.id") - та же ошибка.
  2. @Embeddable class StoryId { @ManyToOne(fetch = FetchType.Lazy) @JoinColumn(name = "STORY_ID") Long id; } // Непонятное исключение нулевого указателя
  3. mappedBy("story") - та же ошибка
  4. Пробовал с mappedBy ('story'), но получал ошибку с повторяющимся столбцом, поэтому пришлось сопоставить его с insertable=false и updatable=false [Hibernate не распознает insertable=false для @EmbeddedId]

Я получаю STORY_ID = null, и поэтому saveAll не удается storyRepository.saveAll(stories), где storyRepository - Хранилище данных Spring

@Table(name = "STORY")
@EqualsAndHashCode
class Story {
   @Id
   @GeneratedValue(stratergy=GenerationType.Auto)
   @Column(name="STORY_ID")
   Long id;

   @Column(name="STORY_NAME")
   String name;

   //@OneToMany(cascade=ALL, mappedBy="taskPKId.storyId.id", fetch = FetchType.Lazy) // tried this as well
   @OneToMany(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy)
   Set<Task> task;
}

@Table(name = "TASK_XREF")
@EqualsAndHashCode
Class Task {
   @EmbeddedId
   TaskPKId taskPKId;

   @Column(name = "TASK_NAME")
   String name;

   @ManyToOne (fetch = FetchType.Lazy, optional = false)
   @JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID", nullable = false, insertable = false, updatable = false) 
   Story story;
}

@Embeddable
@EqualsAndHashCode
Class TaskPKId  implements Serializable {
   TaskId taskId;
   TaskTypeId taskTypeId;
   StoryId storyId;
}

@Embeddable
@EqualsAndHashCode
class StoryId implements Serializable {
   @Column(name = "STORY_ID")
   Long id;
}

Таблицы:

  1. STORY [STORY_ID, STORY_NAME]
  2. TASK_XREF [(TASK_ID(FK), TASK_TYPE_ID(FK), STORY_ID(FK)) PK, TASK_NAME]

История вставляется (перед фиксацией конечно), но завершается неудачно, потому что STORY_ID отправляется как ноль в TASK_XREF для следующих вставок

Ответы [ 2 ]

1 голос
/ 19 мая 2019

Я не совсем уверен, почему ваша конфигурация не работает. У меня похожая конфигурация в одном из моих проектов, которая работает просто отлично. Однако мне удалось найти решение, добавив аннотацию @MapsId к ManyToOne в классе Task. (см. Может кто-нибудь объяснить мне @MapsId в hibernate? для объяснения о MapsId) Я также удалил inserttable = false и Updatable = false. Ниже приведен код.

Мне не удалось заставить MapsId работать с классом StoryId, поэтому я изменил тип TaskPKID.storyId с StoryId на long. Класс StoryId, кажется, не добавляет много, так что, надеюсь, это не составляет большой проблемы. Если вы найдете решение, пожалуйста, дайте мне знать в комментариях!

Кстати, у вашего кода много проблем. Существует множество опечаток и сопоставление OneToMany со свойством, которое не является коллекцией (что не разрешено). Это затруднило мне отладку проблемы. Пожалуйста, не забудьте опубликовать код лучшего качества в своих вопросах в следующий раз.

Вот класс Task, как я его реализовал:

@Entity
@Table(name = "TASK_XREF")
class Task {
    @EmbeddedId
    TaskPKId taskPKId;

    @Column(name = "TASK_NAME")
    String name;
    @MapsId("storyId")
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "STORY_ID")
    Story story;

    //getters, setters

}

А вот класс TaskPKID:

@Embeddable
class TaskPKId  implements Serializable {
        long taskId;
        long taskTypeId;
        @Column(name="STORY_ID")
        long storyId;

    public long getTaskId() {
        return taskId;
    }

    public void setTaskId(long taskId) {
        this.taskId = taskId;
    }

    public void setTaskTypeId(long taskTypeId) {
        this.taskTypeId = taskTypeId;
    }
}
0 голосов
/ 19 мая 2019

Я не уверен, чего вы хотите достичь, но похоже, что вы объединили аннотацию @OneToMany с @OneToOne -подобной реализацией (которая может привести к неожиданному поведению, подобному этому).

Возможные решения:

  1. Если одной истории принадлежит несколько задач

    // Story.java     
    @OneToMany(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy)
    Set<Task> task; // basically Set, List or any other collection type
    // Task.java
    @ManyToOne (fetch = FetchType.Lazy, optional = false)
    @JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID") 
    Story story;
    
  2. Если одной истории принадлежит только одно задание

    // Story.java 
    @OneToOne(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy)
    Task task;
    // Task.java
    @OneToOne (fetch = FetchType.Lazy, optional = false)
    @JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID") 
    Story story;
    

Дополнительная информация: @ OneToOne @ OneToMany

...