LazyInitializationException для поля Id с hibernate + Lombok

Я столкнулся с проблемой ленивой инициализации, когда добавил проект Lombok в свой проект гибернации и использовал его @Getter и @Setter в классе сущности. Классы сущностей аннотированы @Entity Javax.persistence, поскольку я использую hibernate 5.

Проблема с трассировкой стека: -

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:146)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:259)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73)
    at com.capehenry.domain.user.User_$$_jvst52e_9.getId(User_$$_jvst52e_9.java)
    at com.capehenry.business.rs.course.SeatRequestResource.validateSeatRequestCancel(SeatRequestResource.java:338)
    at com.capehenry.business.rs.course.SeatRequestResource.cancel(SeatRequestResource.java:220)

Все работало нормально с приведенным ниже кодом

@Entity
@Audited
@Table(name = "seat_request")
public class SeatRequest extends BaseEntity {

    private CourseSchedule courseSchedule;

@ManyToOne(fetch = FetchType.LAZY)
 @JoinColumn(name = "courseScheduleId", nullable = false)
public CourseSchedule getCourseSchedule() {
    return courseSchedule;
}

public void setCourseSchedule(CourseSchedule courseSchedule) {
    this.courseSchedule = courseSchedule;
}

Когда я выполняю searchRequest.getCourseSchedule (). GetId (), он работает в состоянии покоя вне транзакции.

Как только я изменяю код на приведенный ниже (добавляю ломбок), searchRequest.getCourseSchedule (). GetId () на уровне покоя начинает выбрасывать lazyInitializationException: -

@Entity
@Audited
@Table(name = "seat_request")
@Setter
public class SeatRequest extends BaseEntity {

    @ManyToOne(fetch = FetchType.LAZY, optional=false)
    @JoinColumn(name = "courseScheduleId", nullable = false)
    private CourseSchedule courseSchedule;

ПРИМЕЧАНИЕ :- 1) У меня обязательно использовать Lombok project
2) Мне нужно использовать searchRequest.getCourseSchedule (). GetId () вне Sevrice и trasaction

Пожалуйста, предложите решение, заранее спасибо!

Так почему бы просто EAGER не получить идентификатор? Ленивая выборка, как правило, является хорошей стратегией для вещей, которые вам не обязательно нужны постоянно, поле идентификатора достаточно важно, чтобы просто получать данные с нетерпением.

Gimby 02.05.2018 10:53
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
1 181
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

I have to use searRequest.getCourseSchedule().getId() outside Service and transaction

Я заметил это только что ... Если вы находитесь за пределами службы и транзакции, у вас всегда будет это исключение. Попробуйте использовать FetchType.EAGER и он должен работать.

Когда вы находитесь вне транзакции, ваши сущности отсоединяются, это означает, что все коллекции, которые вы пометили как ленивые, не будут загружены. Таким образом, у вас есть два варианта: первый - выполнить все вызовы геттеров коллекций внутри транзакции, второй - пометить вашу коллекцию как готовую, поэтому, когда Hibernate загружает объект, он также немедленно загружает указанную коллекцию. В качестве альтернативы вы можете сопоставить DTO свою сущность внутри транзакции. Пока вы находитесь в транзакции, получатели ленивого загруженного поля всегда будут работать, поэтому преобразователь в DTO будет иметь доступ ко всей информации. Как только DTO выйдет из транзакции, у вас будет доступ ко всем полям, которые вы сопоставили, и вы сможете делать все, что захотите.

Спасибо за быстрый ответ .. Я уже использовал FethcType.LAZY. И меня беспокоит то, что он работал раньше ... Я добавил свой старый код, поскольку я пропустил, что у меня были аннотации к методу получения, а не на уровне поля, пока он работал вне транзакции.

Swati Joshi 02.05.2018 11:17

Вы пробовали использовать аннотации для полей без ломбока?

Lorelorelore 02.05.2018 11:25

нет .. Я собирался это сделать .. но пока нашел эту ссылку stackoverflow.com/questions/2593722/… Итак, теперь пытаюсь получить доступ type = property

Swati Joshi 02.05.2018 11:31

Сообщите нам, если это поможет

Lorelorelore 02.05.2018 11:34

Я нашел решение .. поставлю как ответ на этот вопрос .. Спасибо за помощь @Lore

Swati Joshi 02.05.2018 13:11

Я заметил, что сделал ошибку: я имел в виду EAGER, а не LAZY при аннотации FetchType. Однако как вы ее решили?

Lorelorelore 02.05.2018 20:31

Я добавил решение как ответ на этот вопрос

Swati Joshi 03.05.2018 13:57
Ответ принят как подходящий

Вот как я наконец решил проблему!
Я думал, что проблема началась после интеграции с проектом Lombok, но проблема началась, когда аннотации были перемещены на уровень поля с уровня метода (свойства). Потерпите длинный ответ. Здесь foreign относится к сторонним таблицам уровня базы данных. Чтобы получить доступ к любому столбцу из вне сделки сторонней таблицы, вам нужно либо использовать FetchType.Eager (который по умолчанию находится в спящем режиме для любого постороннего объекта), либо необходимо присоединиться / запросить эту таблицу.

Но если вы просто хотите получить внешний ключ (столбец), с которым объединены 2 таблицы (в нашем случае идентификатор), и хотите сохранить FetchType.LAZY, вы можете сделать это двумя способами: -

1) Сохраняйте аннотации (manyToOne, JoinColumn и т. д.) В методах получения

2) Если аннотации должны храниться в полевой уровень, тогда напишите еще одну аннотацию в поле внешнего ключа в родительской таблице, которая является - @ Доступ (AccessType.PROPERTY) Итак, в приведенном выше коде для решения я добавил эту аннотацию в поле id, конечно, Расписание

@Entity
@Audited
@Table(name = "course_schedule")
@Getter
@Setter
public class CourseSchedule{
@Id
@GenericGenerator(name = "autoincr", strategy = "native")
@GeneratedValue(generator = "autoincr")
@Column(name = "id", unique = true, nullable = false)
@Access(AccessType.PROPERTY)
protected Long id;
..........
}

Таким образом, никаких изменений в запросе места не потребовалось.

Другие вопросы по теме