【问题标题】:LazyInitializationException for Id field with hibernate + Lombok带有休眠 + Lombok 的 Id 字段的 LazyInitializationException
【发布时间】:2018-05-02 06:52:49
【问题描述】:

当我将 Lombok 项目添加到我的休眠项目中并在实体类上使用它的 @Getter@Setter 时,我遇到了惰性初始化问题。 实体类使用 Javax.persistence 的 @Entity 进行注释,因为我使用的是 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) 我必须强制使用 Lombok 项目
2)我必须在Sevrice和trasaction之外使用searRequest.getCourseSchedule().getId()

请提出解决方案,在此先感谢!

【问题讨论】:

  • 那么为什么不直接获取 ID 呢?对于您不一定总是需要的东西,延迟获取通常是一个很好的策略,ID 字段非常重要,可以急切地获取。

标签: java spring hibernate lombok lazy-initialization


【解决方案1】:

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

我刚刚注意到这一点...如果您不在服务和事务之外,您将始终遇到该异常。尝试使用FetchType.EAGER,它应该可以工作。

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

【讨论】:

  • 感谢您的快速回复。我已经使用过 FethcType.LAZY。我担心的是它以前可以工作。我添加了我的旧代码,因为我错过了在事务外部工作时我在 getter 方法上而不是在字段级别上的注释。
  • 您是否尝试过在没有 lombok 的字段上使用注释?
  • no.. 我正要这样做.. 但同时找到这个链接stackoverflow.com/questions/2593722/… 所以现在尝试访问 type = property
  • 我找到了解决方案..将作为这个问题的答案..感谢您的帮助@Lore
  • 我已添加解决方案作为此问题的答案
【解决方案2】:

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

但是,如果您只想获取连接 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;
..........
}

因此无需更改席位请求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    • 2020-02-27
    • 1970-01-01
    • 2018-07-31
    • 2010-10-22
    • 1970-01-01
    相关资源
    最近更新 更多