hibernate延迟加载和spring的userdetails

lnlaulya  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(248)

我有一个无状态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]
我如何为我的用户和团队建模,以便
团队数据仅在必要时加载
必要时我可以手动加载数据

bqujaahr

bqujaahr1#

如果需要不同的加载开始方式,可以使用:
查询时使用本机sql
具有类似join-fetch结构的jpql
实体图(https://www.baeldung.com/jpa-entity-graph)使用这种方式加载的主要好处是对数据库的单个请求。你可以读更多https://thorben-janssen.com/lazyinitializationexception/
您的对象处于非附加状态-这就是lazyinitializationexception的原因(例如,您可以将其移动到其他状态以加载您的对象)

entityManager.merge(deatachedEntity);

相关问题