Hibernate懒加载导致无法正常进行读取token信息

简介: 在开发带有JWT认证的项目时,可能会遇到登录后调用用户接口返回401未授权的问题。通过查看Spring日志发现,原因是实体对象的关联集合(如`User.roles`)使用了`FetchType.LAZY`,导致会话关闭后无法加载关联数据。解决方法包括:1) 将`FetchType.LAZY`改为`EAGER`;2) 使用JPQL/HQL显式预加载;3) 确保操作在事务范围内或启用OSIV模式;4) 手动初始化关联集合;5) 使用DTO投影减少实体暴露。根据场景选择合适方案,优化性能与稳定性。

编写完一个拥有jwt认证的项目后,在进行测试时,发现已经登录获得token后,调用用户接口,仍然是401未授权状态

查看Spring日志发现

failed to lazily initialize a collection of role: com.test.simpleLoginRegister.model.User.roles: could not initialize proxy - no Session

分析原因在FetchType.LAZY上:

在查询出该实体对象时想使用其关联对象时比如get()等操作,就会报标题错误,主要原因是不在同一会话中,FetchType.LAZY只在实体对象想使用其关联对象时进行才进行查询数据库加载,可是你查询实体对象语句结束后会话就失效了,从而加载不了关联对象

解决:

本项目因为内容不多,所以直接改为FetchType.EAGER

修改Hibernate加载方式.png

其他方法参考:

一、调整Fetch加载策略

  1. 将延迟加载改为立即加载
    在关联属性(如roles)的注解中,将fetch属性设置为FetchType.EAGER,强制在加载主实体时直接加载关联集合。
@ManyToMany(fetch = FetchType.EAGER)
private Set<Role> roles;

适用场景​:关联数据较小且频繁访问时。但需注意,全局改为EAGER会导致查询性能下降(N+1问题)。

  1. 通过JPQL或HQL显式预加载
    在查询时使用JOIN FETCH语句,主动加载关联集合:
@Query("SELECT u FROM User u JOIN FETCH u.roles WHERE u.id = :id")
User findUserWithRolesById(@Param("id") Long id);

优势​:避免全局EAGER的副作用,按需加载。


二、管理Session生命周期

  1. 确保操作在事务范围内
    在Service层方法上添加@Transactional注解,确保整个方法执行期间Session处于打开状态:
@Transactional
public User getUserWithRoles(Long id) {
    User user = userRepository.findById(id);
    user.getRoles().size(); // 触发加载
    return user;
}

注意​:事务边界需覆盖到数据访问和业务逻辑处理。

  1. 使用Open Session in View模式(OSIV)
    在Web应用中,通过配置OpenSessionInViewFilterOpenSessionInViewInterceptor,将Session生命周期延长到请求处理结束后。例如在Spring Boot中:
spring.jpa.open-in-view=true

适用场景​:视图层(如Controller或JSP)需要访问延迟加载的数据。但需注意,此模式可能因长Session占用连接池资源,高并发场景慎用。


三、手动初始化关联集合

  1. 在Session关闭前手动触发加载
    在DAO层或Service层,通过调用集合的size()iterator()等方法强制初始化:
Hibernate.initialize(user.getRoles());

适用场景​:明确知道需要访问哪些关联数据时,精准控制加载时机。


四、其他优化方案

  1. DTO投影与序列化处理
    在返回数据到前端时,通过DTO或VO剥离实体关联,避免因序列化触发延迟加载:
public class UserDTO {
    private Long id;
    private String name;
    private List<String> roleNames; // 手动映射角色名
}

优势​:减少数据传输量,避免序列化异常。

  1. 检查事务配置与异常回滚
    确保@TransactionalrollbackFor属性包含实际抛出的异常类型,避免事务提前回滚导致Session关闭。

总结选择方案

  • 简单场景​:直接使用FetchType.EAGER@Transactional注解。
  • Web应用​:启用OSIV模式(需权衡性能)。
  • 复杂业务逻辑​:通过JPQL预加载或手动初始化。
  • 前后端分离架构​:优先采用DTO投影,避免实体直接暴露。

若仍存在问题,可能需要检查Hibernate配置(如hibernate.enable_lazy_load_no_trans)、连接池设置及事务传播行为。

相关文章
|
1月前
|
Java Spring
jwt解析方法找不到(Cannot resolve method ‘parseClaimsJws‘ in ‘JwtParserBuilder‘ )
解决Cannot resolve method ‘parseClaimsJws‘ in ‘JwtParserBuilder‘
|
28天前
|
Kubernetes Cloud Native 安全
云原生机密计算新范式 PeerPods技术方案在阿里云上的落地和实践
PeerPods 技术价值已在阿里云实际场景中深度落地。
|
26天前
|
缓存 监控 安全
通义大模型与现有企业系统集成实战《CRM案例分析与安全最佳实践》
本文档详细介绍了基于通义大模型的CRM系统集成架构设计与优化实践。涵盖混合部署架构演进(新增向量缓存、双通道同步)、性能基准测试对比、客户意图分析模块、商机预测系统等核心功能实现。同时,深入探讨了安全防护体系、三级缓存架构、请求批处理优化及故障处理机制,并展示了实时客户画像生成和动态提示词工程。通过实施,显著提升客服响应速度(425%)、商机识别准确率(37%)及客户满意度(15%)。最后,规划了技术演进路线图,从单点集成迈向自主优化阶段,推动业务效率与价值持续增长。
|
23天前
|
存储
《仿盒马》app开发技术分享--未完成订单列表展示逻辑优化(61)
上一节我们实现订单与优惠券的联合提交时,我去到订单列表页面查看生成的订单信息,发现现在的订单从信息展示到价格计算全都是有问题的。所以紧急的把对应的问题修改一下。
117 70
|
9天前
|
机器学习/深度学习 人工智能 算法
Wi-Fi老是卡?不如试试让“深度学习”来当网络管家!
Wi-Fi老是卡?不如试试让“深度学习”来当网络管家!
121 68
|
17天前
|
监控 安全 搜索推荐
进程分析工具,系统进程监控与管理工具推荐
Process Hacker是一款免费开源的Windows系统进程监控与管理工具,支持查看进程信息、终止或暂停进程、设置优先级等操作。它提供详细的系统资源监控、安全检测及高级功能如内存分析和插件扩展,适用于性能优化、安全排查、开发调试及系统管理等多种场景。
150 63
|
8天前
|
Java 索引
Java ArrayList中的常见删除操作及方法详解。
通过这些方法,Java `ArrayList` 提供了灵活而强大的操作来处理元素的移除,这些方法能够满足不同场景下的需求。
69 30
|
8天前
|
NoSQL Java Redis
基于Redisson和自定义注解的分布式锁实现策略。
在实现分布式锁时,保证各个组件配置恰当、异常处理充足、资源清理彻底是至关重要的。这样保障了在分布布局场景下,锁的正确性和高效性,使得系统的稳健性得到增强。通过这种方式,可以有效预防并发环境下的资源冲突问题。
66 29
|
8天前
|
JavaScript 前端开发 开发者
讲述Vue框架中用于对象响应式变化的Object.defineProperty函数。
综上所述,Vue.js通过 `Object.defineProperty()`提供了强大的响应式能力,使得状态管理变得简洁高效。这种能力是Vue.js受到广大开发者青睐的重要原因之一。尽管Vue 3.x使用Proxy替代了该方法,但对于Vue 2.x及其之前版本,`Object.defineProperty()`是理解Vue.js内部工作机制不可或缺的一部分。
61 27