Java Spring JPA、延迟初始化和Dto

Java Spring JPA、延迟初始化和Dto,java,hibernate,jpa,dto,Java,Hibernate,Jpa,Dto,我试图在登录后(从登录成功过滤器)获取用户的配置文件数据,但我发现延迟加载数据的异常。请参见以下示例代码: AuthenticationSuccessHandler.java @Component public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { @Autowired private UserService userService;

我试图在登录后(从登录成功过滤器)获取用户的配置文件数据,但我发现延迟加载数据的异常。请参见以下示例代码:

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);
    }
}
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;
    }
}
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);
    }
}
public class UserLoginResponseDto {

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

}
UserService.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);
    }
}
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;
    }
}
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);
    }
}
public class UserLoginResponseDto {

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

}
public类UserService实现userdetails服务,TokenService{
@自动连线
私有用户存储库用户存储库;
@事务(只读=真)
公共用户登录响应登录(字符串电子邮件){
Optional userOptional=userRepository.findByEmailIgnoreCase(电子邮件);
UserModel UserModel=userOptional.get();
UserLoginResponseTo UserLoginResponseTo=userModel.ToUserLoginResponseTo();
返回userLoginResponseDto;
}
}
UserModel.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);
    }
}
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;
    }
}
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);
    }
}
public class UserLoginResponseDto {

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

}
公共类用户模型{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(nullable=false,unique=true,Updateable=false)
私有UUID;
[还有几个字段]
@列(长度=256,可空=false,唯一=true,可更新=false)
私人字符串电子邮件;
@OneToMany(cascade={CascadeType.ALL})
私有列表角色模型;
公共用户登录回复TouserLoginResponseTo(){
返回新的UserLoginResponseDto().setId(id).setEmail(email).setRoles(roleModels);
}
}
UserLoginResponseDto.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);
    }
}
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;
    }
}
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);
    }
}
public class UserLoginResponseDto {

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

}
public类用户登录回复到{
私有UUID;
私人字符串电子邮件;
私有列表角色;
}
当在
AuthenticationSuccessHandler
中序列化UserLoginResponseDto类型的对象时,我会看到以下错误消息-

org.hibernate.LazyInitializationException:未能延迟初始化角色集合:UserModel.roleModels,无法初始化代理-无会话

QQ-如何在不使用以下任何技术的情况下正确解决此问题

  • [反模式]在视图中打开
  • [反模式]hibernate.enable\u lazy\u load\u no\u trans
  • FetchType.EAGER

您的问题是将实际的惰性
列表
传递到
设置角色
,这不会触发满负载。这表明(立即)虽然您已将顶级数据库类与顶级DTO分离,但这是一种“浅”分离,不能完全实现值。您还没有说明
RoleModel
是实体还是可嵌入的,这很重要

因此,第一步是将项目复制到非JPA表单中。如果
RoleModel
embedded(本质上是一个POJO),这可以像
setRoles(新的ArrayList(roles))
一样简单。否则,您需要一个嵌套的DTO,此时可能会考虑一些类似于MaSpult.

的东西。
但是,无论哪种情况,您都可能遇到N+1问题。事实上,在这种情况下,您确实需要一个急切的获取,这就是JPA实体图的用途。您可以告诉Spring Data只在您需要的时候才急切地获取列表,这是一个完美的例子,说明了何时进行此操作。

RoleModel
是一个实体,我们可以从这个映射中看到:
@OneToMany(cascade={CascadeType.ALL})private list roleModels