java - Spring @Transactional 导致 NoClassDefFoundError

标签 java spring-boot spring-transactions

一个人请求我帮助他解决他的 Spring Boot 应用程序安全服务中的一个奇怪的错误,经过几个小时的跟踪,我设法修复了该错误,但我真的不知道发生了什么。请查看这些类:

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<>();
}

UserDto:实现Spring的管理用户凭证的接口(interface)

@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
}

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 Boot 应用程序):https://github.com/raizo000/admin_project (他的repo使用嵌入式tomcat,我尝试将其更改为jetty,但这不是原因)

当我第一次使用这 3 个类运行代码时。该行

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帮助修复错误,但会导致另一个延迟初始化错误,我最终在User中更改fetch = FetchType.LAZYfetch = FetchType.EAGER 作为快速修复。

为什么添加 Transactional 会导致 NoClassDefFoundError?删除事务是正确的解决方案还是有更好的解决方案?

最佳答案

当没有找到类时,您应该做的第一件事是清理和构建。 因为,最后的构建节省了一些依赖性。 所以@Transactional在某些损坏的包中找不到@interface。 重建(干净的构建)解决了这个问题。

关于java - Spring @Transactional 导致 NoClassDefFoundError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53563401/

相关文章:

java - Spring Boot 找不到我的 Autowiring 类( Autowiring 成员必须在有效的 Spring bean 中定义)

java - Spring Boot使用pathvariable从url获取id

Spring Transactions - 在未经检查的异常(RuntimeException)后防止回滚

java - Hibernate 嵌套 JoinColumns 会导致从数据库中进行大量查询,并包含不必要的数据

java - 将加密服务从 .Net 移植到 Java

java - 如何为静态 void 方法实现 doNothing() ?

mysql - 创建类路径资源中定义的名称为 'entityManagerFactory' 的 bean 时出错。init 方法调用失败;

javascript - 如何在不同的 id 上更改具有相同输出的显示 css 切换开关?

spring - 为什么JdbcTemplate.batchupdate(sql[])方法在Spring4中使用@transaction注解不回滚?

java - 在 Hibernate 中的非事务类/方法中进行延迟加载