我有一个无状态rest后端。所以没有html视图。只有json和rest端点。身份验证是用json web令牌完成的。客户机在每个请求中发送一个jwt。我的后端从这个jwt的主题声明中获取用户的电子邮件。然后从中的数据库加载usermodel class LiquidoUserDetailsService implements UserDetailsService { ...}
每个用户都是团队的一部分。但这个团队是一个拥有大量信息的大实体。因此,团队只有在必要时才懒散地加载:
用户模型.java
@Entity
@Table(name = "users")
public class UserModel extends BaseModel {
@NotNull
@NonNull
@Column(unique = true)
public String email;
@ManyToOne(fetch = FetchType.LAZY) // only load team info (with all info) if required
public TeamModel team;
[...]
}
现在我有一个服务,它应该返回当前用户的团队:
团队服务.java
@PreAuthorize(HAS_ROLE_USER)
@RequestMapping("/getOwnTeam")
@Transactional // [1]
public TeamModel getOwnTeam() {
// Get currently logged in user (that was loaded with info from JWT)
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
LiquidoAuthUser authUser = (LiquidoAuthUser)authentication.getPrincipal();
// LiquidoAuthUser is the Adapter betwen spring's User and my USerModel
UserModel currentUser = authUser.getLiquidoUserModel()
TeamModel team = currentUser.getTeam() // <=== [2] throws LazyInitializationException
return team
}
现在我想我知道问题出在哪里了。但我还没有一个干净的解决办法。
我的用户模型已加载到 class LiquidoUserDetailsService implements UserDetailsService
但是这种情况很早就发生了,在一个过滤器中,当http请求被处理时。当它缝合 @Transaction
在我的 TeamService
那时候还没有上课。
当代码进入 getOwnTeam()
方法,则启动新事务[1]。但是在那里我不能再懒洋洋地加载用户的团队了[2]
我如何为我的用户和团队建模,以便
团队数据仅在必要时加载
必要时我可以手动加载数据
1条答案
按热度按时间bqujaahr1#
如果需要不同的加载开始方式,可以使用:
查询时使用本机sql
具有类似join-fetch结构的jpql
实体图(https://www.baeldung.com/jpa-entity-graph)使用这种方式加载的主要好处是对数据库的单个请求。你可以读更多https://thorben-janssen.com/lazyinitializationexception/
您的对象处于非附加状态-这就是lazyinitializationexception的原因(例如,您可以将其移动到其他状态以加载您的对象)