我在Spring Boot应用程序中更新实体时遇到此错误。
我有这两个对象
@Entity
public class User {
...
@ManyToMany
@JoinColumn(name="locationId")
@JsonIgnore
private List<Location> locations;
...
//getters and setters
}
然后
@Entity
public class Coupon {
.....
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.DETACH, CascadeType.REFRESH}, fetch = FetchType.LAZY)
private List<Location> locations;
....
//getters and setters
}
在调度程序中,我需要与用户和优惠券进行交互
List<Location> locations = new ArrayList<>();
locations.addAll(user.getLocations());
Coupon coupon = couponService.generateCoupons(CouponType.TIME , contract.getType().getTimeCredit(), locations, couponName);
userService updateUser(user);
generateCoupons
位于@Service
和@Transactional
类;
@Override
public Coupon generateCoupons(CouponType type, int value, List<Location> locations, String couponName) {
Coupon coupon = new Coupon();
coupon.setActive(true);
coupon.setCode(generateRandomCouponCode());
coupon.setCouponCount(0);
coupon.setCouponLimit(1);
coupon.setCouponName(couponName);
LocalDateTime limit = LocalDateTime.now().plusYears(1);
coupon.setDateLimit(Date.from(limit.atZone(ZoneId.systemDefault()).toInstant()));
coupon.setLocations(locations);
coupon.setStartDate(new Date());
coupon.setType(type);
coupon.setUserLimit(1);
coupon.setValue(value);
return saveCoupon(coupon);
}
当试图保留优惠券时我得到了异常,我不知道为什么,一切都发生在交易中......
这是完整的堆栈跟踪
aused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: it.besmart.eshare.persistence.model.User.locations, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:587)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:204)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:148)
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:261)
at org.hibernate.collection.internal.PersistentBag.addAll(PersistentBag.java:328)
at it.besmart.eshare.service.CouponService.generateCoupons(CouponService.java:248)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy171.generateCoupons(Unknown Source)
at it.besmart.eshare.scheduler.cronjobs.CheckContract.executeInternal(CheckContract.java:102)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
... 1 common frames omitted
答案 0 :(得分:0)
先生,在这里你没有指定获取类型渴望。默认情况下,它是懒惰的提取。 但是你试图热切地获取它。所以一个例外 发生在这里。
user. getLocation();//Failed to lazy initialize User.
// locations the Exception what we seen in console
只需像这样修改用户模型类
@ManytoMany(fetch=FetchType.EAGER)
@JoinColumn(name="locationId")
@JsonIgnore
private List<Location> locations;
答案 1 :(得分:0)
默认情况下,会话管理配置设置为在提交事务时关闭会话。 如果您要使用惰性实体,立即获取延迟实体是一种很好的做法。就像在这个JPQL查询中一样:
select User u from User join fetch u.locations
否则,获取用户然后获取位置应该包含在事务方法中。在你的情况下,hibernate尝试获取位置,但看到已经没有他附加的会话。你需要定义@Transaction方法将从你获得用户的地方开始,正如我在调度程序中所理解的那样。 但要小心,最重要的是不要延迟事务的持续时间,因此对于纯数据处理,你应该创建一个单独的@Transactional方法。