当我将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()
请提出解决方案,提前致谢!!
答案 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;
..........
}
因此座位申请无需更改。