LazyInitializationException для поля Id с гибернацией + Lombok - PullRequest
0 голосов
/ 02 мая 2018

Я столкнулся с ленивой проблемой инициализации, когда я добавил проект Lombok в свой проект hibernate и использовал его @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;
}

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

Как только я изменяю код ниже (добавьте lombok), searRequest.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) Я должен в обязательном порядке использовать проект Ломбок
2) Я должен использовать searRequest.getCourseSchedule (). GetId () вне Sevrice и trasaction

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

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

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

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

1) Хранить аннотации (manyToOne, JoinColumn и т. Д.) Для методов получения

2) Если аннотации должны храниться на уровне поля , тогда напишите еще одну аннотацию на поле внешнего ключа в родительской таблице, которая будет - @ Access (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;
..........
}

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

0 голосов
/ 02 мая 2018

Я должен использовать searRequest.getCourseSchedule (). GetId () вне Сервиса и транзакции

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...