当前位置: 首页 > 知识库问答 >
问题:

如何在使用转换器的Spring控制器中解决“org.hibernate.lazyInitializationException:无法初始化代理-没有会话”

郭兴平
2023-03-14

我正在从以下位置迁移一个项目:

    null
// CustomUser.java
@Entity
@Access(AccessType.FIELD)
@Table(name = "users")
public class CustomUser implements Serializable {
    ...
    @Id
    @GeneratedValue//details omitted
    @GenericGenerator//details omitted
    @Column(name = "id", insertable = true, updatable = true, unique = true, nullable = false)
    private Long id;

    @Column(name = "name")
    private String name;

    public String getName() { return name; }
}

// UserController.java
@RequestMapping(value = "/user/{userId}/", method = RequestMethod.GET)
public String showUser(@PathVariable("userId") CustomUser user) {
    System.out.println("user name is [" + user.getName() + "]");
    return "someTemplate";
}

// UserService.java
@Service
public class UserServiceImpl implements UserService {
    @Autowired UserRepository userRepository;

    @Override
    public User findUserById(Long userId) {
        return userRepository.getOne(userId);
    }
}

// UserRepository.java
public interface UserRepository extends JpaRepository<CustomUser, Long> { }

// UserConverter.java
@Component
public class UserConverter implements Converter<String, CustomUser> {
    @Autowired UserService userService;

    @Override
    public CustomUser convert(String userId) {
        CustomUser user = userService.findUserById(SomeUtilClass.parseLong(userId));
        return user;
    }
}

但是,现在我得到了org.hibernate.LazyInitializationException。当我试图在“showUser”方法中打印出用户名--甚至只是“println(user)”而不访问字段时,就会出现这种情况。

我从搜索中得到的大多数信息表明,这个异常来自于一个对象有一个缓慢加载的子对象集合(就像我的CustomUser有一个权限对象集合或映射到不同数据库表的东西)。但在这个例子中,我甚至没有这样做,这只是物体上的一个场。

目前我的最佳猜测是,这是由于某种Hibernate会话在转换器完成工作后被终止,因此在控制器中我没有有效的会话。(虽然我也不知道CustomUser对象为什么会返回不可用,但我并不试图获取子集合)。

共有1个答案

仲浩旷
2023-03-14

眼前的问题来自userRepository.getOne(userId)的使用。它是使用EntityManager.GetReferenceSimpleJarepository中实现的。此方法只返回一个代理,该代理只包含其ID。并且只有当一个属性被访问时,这些属性才会被惰性加载。这包括简单的属性,如name

立即的解决方法是使用findone,它应该加载实体的所有EXEAR属性,这些属性应该包括简单属性,这样异常就会消失。

请注意,这将稍微改变您的转换器的行为。当id在数据库中不存在时,当前版本不会失败,因为它从不检查。新的一个将获得一个空的可选项,您必须将其转换为null或抛出一个异常。

确保在调用转换器之前启动事务。

@transactional标记控制器,并将用户(再次)加载到控制器中。

 类似资料:
  • 问题内容: 我有2台物理服务器,我的Web应用程序命中该服务器由负载均衡器管理。我总是得到- org.hibernate.LazyInitializationException:无法初始化代理-没有会话 当其中一台服务器受到攻击而另一台服务器运行平稳而没有任何问题时。我有一个由应用程序启用和管理的本地托管缓存存储。仅当尝试从一个表访问一个特定的列时,才会发生此异常。不管选择哪个服务器,其余的操作都

  • 问题内容: 我试图从数据库中的对象进行简单加载,但出现错误“无法初始化代理-没有会话”,知道吗?谢谢 问题答案: 尝试添加到validate方法: 发生的事情是,因为没有注释,所以没有与该方法关联的会话,并且每个查询都将在其自己的会话中运行,该会话随后将立即关闭。 该方法始终返回一个代理,与之不同(请参阅此处,了解load与get之间的差异)。 因此,返回了代理,但是由于缺少代理,因此立即关闭了创

  • 我试图从DB中的一个对象做一个简单的加载,但是我得到的错误是“Could not initialize proxy-no session”,有什么想法吗?谢谢

  • 我正在尝试使用Primeface JSF Spring Boot做一个示例User CRUD页面。在页面上,我有一个启用LazyLoding的表。我的User对象没有1对N或N对1字段,都是原始字段,在到达时不需要数据库访问或初始化。(所以FetchType.EAGER不会有帮助) 当试图在弹出窗口上显示用户列表中的用户时,出现以下异常: 为什么 JSF 组件尝试从数据库中更新对象以获取 1 比

  • 问题内容: 我得到以下异常: 当我尝试从以下几行拨打电话时: 我首先实现了这样的方法: 并得到了例外。然后一位朋友建议我始终测试该会话并获取当前会话,以避免出现此错误。所以我这样做: 但仍然会出现相同的错误。我已经阅读了很多有关此错误的内容,并找到了一些可能的解决方案。其中之一是将lazyLoad设置为false,但是不允许这样做,因此建议我控制会话 问题答案: 这是错误的,因为您在提交事务时将会

  • 我得到以下例外情况: 当我尝试从main调用以下线路时: