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