Spring @Transactional 导致 NoClassDefFoundError
Spring @Transactional cause NoClassDefFoundError
一个人请我帮他解决他的 spring 启动应用程序安全服务中的一个奇怪错误,经过几个小时的跟踪我设法修复了这个错误,但我真的不知道发生了什么。请查看这些 classes:
Class User
: 数据库中的用户信息
@Getter
@Setter
@Entity
@Table(name = "user", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_name"})})
public class User extends DateAudit implements Serializable {
// Id, username, password and constructor... not really important
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> role = new HashSet<>();
}
Class UserDto
: 实现 Spring 的界面以管理用户凭证
@Getter
@Setter
@AllArgsConstructor
public class UserDto implements org.springframework.security.core.userdetails.UserDetails {
private long id;
private String Username;
@JsonIgnore
private String password;
private Collection<? extends GrantedAuthority> authorities;
public static UserDto create(User user) {
List<GrantedAuthority> authorities = user.getRole().stream()
.map(role -> new SimpleGrantedAuthority(role.getName().name())).collect(Collectors.toList());
return new UserDto(user.getId(), user.getUserName(), user.getPassword(), authorities);
}
// implement interface's methods, only getters, not important
}
Class CustomUserService
: 授权服务
@Service
public class CustomUserService implements org.springframework.security.core.userdetails.UserDetailsService {
private final UserRepository userRepository;
@Autowired
public CustomUserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
@Transactional
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
User user = userRepository.findUserByUserName(userName).orElseThrow(() -> {
return null;
});
return UserDto.create(user);
}
}
可以在这里找到完整的源代码(它只是一个简单的 spring 启动应用程序,带有一些 classes):https://github.com/raizo000/admin_project(他的 repo 使用嵌入式 tomcat ,我试图将其更改为 jetty 但这不是原因)
当我 运行 第一次用这 3 个 class 编写代码时。该行
return UserDto.create(user);
给我一个NoClassDefFoundError
:
WARN 7252 --- [qtp223566397-22] org.eclipse.jetty.server.HttpChannel : /login
java.lang.NoClassDefFoundError: com/example/admin/dto/UserDto
at com.example.admin.services.CustomUserService.loadUserByUsername(CustomUserService.java:28) ~[classes/:na]
at com.example.admin.services.CustomUserService$$FastClassBySpringCGLIB$$b9234a59.invoke(<generated>) ~[classes/:na]
....
我检查了jar文件,在正确的目录下有一个UserDto.class文件。
删除 @Transactional
有助于修复错误,但会导致另一个延迟初始化错误,我最终将 fetch = FetchType.LAZY
in User
class 更改为 fetch = FetchType.EAGER
作为快速修复。
为什么添加 Transactional 会导致 NoClassDefFoundError?删除 Transactional 是正确的解决方案还是有更好的解决方案?
当找不到 class 时,您应该做的第一件事就是清理和构建。
因为,最后一次构建节省了一些依赖性。
所以 @Transactional @interface 在一些损坏的包中找不到。
重建(干净构建)解决了它。
一个人请我帮他解决他的 spring 启动应用程序安全服务中的一个奇怪错误,经过几个小时的跟踪我设法修复了这个错误,但我真的不知道发生了什么。请查看这些 classes:
Class User
: 数据库中的用户信息
@Getter
@Setter
@Entity
@Table(name = "user", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_name"})})
public class User extends DateAudit implements Serializable {
// Id, username, password and constructor... not really important
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> role = new HashSet<>();
}
Class UserDto
: 实现 Spring 的界面以管理用户凭证
@Getter
@Setter
@AllArgsConstructor
public class UserDto implements org.springframework.security.core.userdetails.UserDetails {
private long id;
private String Username;
@JsonIgnore
private String password;
private Collection<? extends GrantedAuthority> authorities;
public static UserDto create(User user) {
List<GrantedAuthority> authorities = user.getRole().stream()
.map(role -> new SimpleGrantedAuthority(role.getName().name())).collect(Collectors.toList());
return new UserDto(user.getId(), user.getUserName(), user.getPassword(), authorities);
}
// implement interface's methods, only getters, not important
}
Class CustomUserService
: 授权服务
@Service
public class CustomUserService implements org.springframework.security.core.userdetails.UserDetailsService {
private final UserRepository userRepository;
@Autowired
public CustomUserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
@Transactional
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
User user = userRepository.findUserByUserName(userName).orElseThrow(() -> {
return null;
});
return UserDto.create(user);
}
}
可以在这里找到完整的源代码(它只是一个简单的 spring 启动应用程序,带有一些 classes):https://github.com/raizo000/admin_project(他的 repo 使用嵌入式 tomcat ,我试图将其更改为 jetty 但这不是原因)
当我 运行 第一次用这 3 个 class 编写代码时。该行
return UserDto.create(user);
给我一个NoClassDefFoundError
:
WARN 7252 --- [qtp223566397-22] org.eclipse.jetty.server.HttpChannel : /login
java.lang.NoClassDefFoundError: com/example/admin/dto/UserDto
at com.example.admin.services.CustomUserService.loadUserByUsername(CustomUserService.java:28) ~[classes/:na]
at com.example.admin.services.CustomUserService$$FastClassBySpringCGLIB$$b9234a59.invoke(<generated>) ~[classes/:na]
....
我检查了jar文件,在正确的目录下有一个UserDto.class文件。
删除 @Transactional
有助于修复错误,但会导致另一个延迟初始化错误,我最终将 fetch = FetchType.LAZY
in User
class 更改为 fetch = FetchType.EAGER
作为快速修复。
为什么添加 Transactional 会导致 NoClassDefFoundError?删除 Transactional 是正确的解决方案还是有更好的解决方案?
当找不到 class 时,您应该做的第一件事就是清理和构建。 因为,最后一次构建节省了一些依赖性。 所以 @Transactional @interface 在一些损坏的包中找不到。 重建(干净构建)解决了它。