springjpa、延迟初始化和dto

ttygqcqt  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(352)

这个问题在这里已经有答案了

如何修复hibernate lazyinitializationexception:未能延迟初始化角色集合,无法初始化代理-无会话(13个答案)
14天前关门了。
我试图获取用户的配置文件数据后登录(从登录成功过滤器),但我看到了一个例外,延迟加载数据。请参见以下示例代码:
authenticationsuccesshandler.java验证

@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Autowired
    private UserService userService;

    @Autowired
    private Gson gson;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws ServletException, IOException {

        User user = (User) authentication.getPrincipal();
        UserLoginResponseDto userLoginResponseDto = userService.login(user.getUsername());

        response.setStatus(HttpStatus.OK.value());
        response.setContentType("application/json; charset=UTF-8");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.getWriter().println(gson.toJson(userLoginResponseDto));
        response.getWriter().flush();

        clearAuthenticationAttributes(request);
    }
}

用户服务.java

public class UserService implements UserDetailsService, TokenService {

    @Autowired
    private UserRepository userRepository;

    @Transactional(readOnly = true)
    public UserLoginResponseDto login(String email) {
        Optional<UserModel> userOptional = userRepository.findByEmailIgnoreCase(email);
        UserModel userModel = userOptional.get();
        UserLoginResponseDto userLoginResponseDto = userModel.toUserLoginResponseDto();
        return userLoginResponseDto;
    }
}

用户模型.java

public class UserModel {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(nullable = false, unique = true, updatable = false)
    private UUID id;

    [A FEW MORE FIELDS]

    @Column(length = 256, nullable = false, unique = true, updatable = false)
    private String email;

    @OneToMany(cascade = { CascadeType.ALL })
    private List<RoleModel> roleModels;

    public UserLoginResponseDto toUserLoginResponseDto() {
        return new UserLoginResponseDto().setId(id).setEmail(email).setRoles(roleModels);
    }
}

userloginresponsedto.java

public class UserLoginResponseDto {

    private UUID id;
    private String email;
    private List<RoleModel> roles;

}

在中序列化userloginresponsedto类型的对象时 AuthenticationSuccessHandler ,我看到以下错误消息-
org.hibernate.lazyinitializationexception:未能延迟初始化角色集合:usermodel.rolemodels,无法初始化代理-无会话
我如何正确解决这个问题而不采用以下任何技术?
[反模式]在视图中打开
[反模式]hibernate.enable\u lazy\u load\u no\u trans
fetchtype.eager文件

lyfkaqu1

lyfkaqu11#

你的问题是你通过了真正的懒惰 List 进入 setRoles ,不会触发满载。这表明(立即)虽然您已经将顶级数据库类与顶级dto分离,但这是一种“浅层”分离,不能完全实现值。你还没有证明 RoleModel 是实体还是可嵌入的,这很重要。
因此,第一步是将这些项复制到非jpa表单中。如果 RoleModel 可嵌入(本质上是一个pojo),这可以简单到 setRoles(new ArrayList<>(roles)) . 否则,您需要一个嵌套的dto,此时可以考虑mapstruct之类的东西。
不过,无论哪种情况,您都可能遇到n+1问题。实际上,在这种情况下,您确实需要一个急切的获取,这就是jpa实体图的用途。您可以告诉spring数据只有在需要时才急切地获取列表,这是一个很好的例子。

相关问题