spring-boot - Kotlin - 数据类实体抛出 StackOverflowError

标签 spring-boot kotlin

我尝试将 kotlin(版本 1.2.21)与 spring-boot(1.5.9.RELEASE)结合起来。我在使用带有 @Entity 注释的数据类时遇到了问题。我的问题实体如下所示:

@Entity
@Table(name = "APP_USER")
data class AppUser(

    @Column(name = "USERNAME", unique = true)
    private val username: String,

    @Column(name = "PASSWORD")
    private val password: String,

    @Column(name = "IS_ACTIVE")
    val isActive: Boolean,

    @Column(name = "REGISTRATION_DATE_TIME")
    val registrationDateTime: LocalDateTime = SystemTimeManager.getSystemDateTime(),

    @OneToMany(mappedBy = "appUser", cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
    val authorities: MutableSet<UserAuthority> = mutableSetOf()
) : EntityBase(), UserDetails {


   internal fun addRole(authority: UserAuthority) {
      this.authorities.add(authority)
   }

}


@Entity
@Table(name = "USER_AUTHORITY")
data class UserAuthority(
    @ManyToOne
    @JoinColumn(name = "APP_USER_ID", nullable = false)
    val appUser: AppUser,

    @Column(name = "ROLE", length = 50, nullable = false)
    @Enumerated(value = EnumType.STRING)
    private val authority: Authority
) : EntityBase(), GrantedAuthority {

override fun getAuthority(): String {
    return authority.name
    }   
}

如您所见,我们在 AppUser 和 UserAuthority 之间有 @OneToMany 关系。现在我尝试添加一些这样的权限:
authoritiesCollection.forEach { appUser.addRole(UserAuthority(appUser, Authority.valueOf(it))) }

在执行期间,第一个权限始终正确添加到 appUser,但是添加第二个权限会产生 StackOverflowError 和堆栈跟踪
java.lang.StackOverflowError
at security.usermanagement.AppUser.hashCode(AppUser.kt)
at security.usermanagement.UserAuthority.hashCode(UserAuthority.kt)

如果我将这些类设为非数据,它就可以正常工作。我可能可以通过覆盖 hashcode 和 equals 方法来解决这个问题,但是我有很多实体,所以我真的不想。

最佳答案

您在 AppUser 之间存在循环依赖关系和 UserAuthority .在处理 hashCode 时,您需要排除一个以打破循环依赖。

您可以通过将导致循环依赖的属性移动到数据类主体来修复它,这样这些属性将不会用于自动生成的字段。在这种情况下,它将移动 authoritiesAppUser body :

@Entity
@Table(name = "APP_USER")
data class AppUser(

        @Column(name = "USERNAME", unique = true)
        private val username: String,

        @Column(name = "PASSWORD")
        private val password: String,

        @Column(name = "IS_ACTIVE")
        val isActive: Boolean,

        @Column(name = "REGISTRATION_DATE_TIME")
        val registrationDateTime: LocalDateTime = SystemTimeManager.getSystemDateTime(),

) {
    @OneToMany(mappedBy = "appUser", cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
    val authorities: MutableSet<String> = mutableSetOf()

    internal fun addRole(authority: String) {
        this.authorities.add(authority)
    }

}

关于spring-boot - Kotlin - 数据类实体抛出 StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48926704/

相关文章:

spring - 装饰 spring boot 仓库

spring-boot - Spring Boot 2 无法连接到 Redis

generics - 包含泛型的Kotlin函数的内联别名?

kotlin - 如何从终端中的用户获取字符?

spring-boot - 将主题名称数组列表传递给@KafkaListener

java - Spring Boot 找不到 JdbcTemplate 的数据源

java - Spring引导安全: Issue while showing login page in Angular 8

java - 无法创建子事件循环/无法打开新选择器/打开的文件太多

android - 使用 RxJava 和 EventBus 将事件发送回 Activity/fragment

kotlin - 在 Intellij IDE 中编译 Kotlin 时无法删除缓存目录