带有hibernate + Lombok的{id}字段的LazyInitializationException

时间:2018-05-02 06:52:50

标签: java spring hibernate lombok lazy-initialization

当我将Lombok项目添加到我的hibernate项目并在实体类上使用其@Getter@Setter时,我面临着懒惰的inizialization问题。 当我使用hibernate 5时,实体类使用@Entity Javax.persistence进行注释。

发出stacktrace : -

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)我必须强制使用Lombok项目
2)我必须在Sevrice和trasaction之外使用searRequest.getCourseSchedule()。getId()

请提出解决方案,提前致谢!!

2 个答案:

答案 0 :(得分:2)

  

我必须在服务和交易之外使用searRequest.getCourseSchedule()。getId()

我刚刚注意到这一点......如果你不在服务和交易之外,你将永远有这个例外。尝试使用FetchType.EAGER,它应该有效。

当您没有交易时,您的实体将被分离,这意味着您标记为懒惰的所有集合都将被加载。所以你有两个选择:第一个是在事务中执行对集合getter的所有调用,第二个是标记为渴望你的集合,所以当Hibernate加载实体时它也会立即加载引用的集合。或者,您可以在交易中映射到DTO您的实体。只要您在事务中,延迟加载字段的getter将始终有效,因此DTO的映射器将访问所有信息。一旦DTO不在交易中,你就可以访问你已映射的所有字段,而不是做你想做的任何事情。

答案 1 :(得分:1)

以下是我最终解决问题的方法! 我认为问题是在与Lombok项目集成后开始的,但是当注释从方法(属性)级别移动到字段级别时问题就开始了。
请耐心等待我的回答。 这里foreign是指数据库级别的外表 要从外部表的访问事务中访问任何列,您需要使用FetchType.Eager(对于任何外来对象在hibernate中是默认的)或者需要加入/子查询该表。

但是如果你只是想获取连接2个表的外键(列)(在我们的例子中是ID)并且想要保留 FetchType.LAZY 那么你可以在2中执行它方式: -

1)在getter方法上保留注释(manyToOne,JoinColumn等)

2)如果注释必须保留在字段级别,则在父表中的外键字段上再写一个注释 - @Access(AccessType.PROPERTY) 所以在上面的代码中我解决了我在id字段中添加了这个注释当然是Schedule

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

因此座位申请无需更改。