Hibernate不为具有支持属性的Kotlin属性创建连接表

时间:2019-01-03 00:58:20

标签: hibernate jpa kotlin

:: ORIGINAL :: (以下更新)

我有以下内容(简体):

@Entity(name = "Group")
@Table(name = "groups")
data class Group(
    @Column
    override val name: String,

) : CoreGroup {

    @GeneratedValue
    @Id
    val id: Long = 0

    @Transient
    private val _users = mutableSetOf<User>()
    @ManyToMany(cascade = [CascadeType.PERSIST, CascadeType.MERGE])
    override val users get() = _users
}

结果表具有预期的nameid列,但未创建我期望的联接表(groups_users)。如果我删除了后备属性,而只是将users设置为普通属性,它将按预期工作。

我也尝试过对该属性进行@get:@ManyToMany...,这没有任何效果。

如果我将注释放在backing属性上,则:

@ManyToMany(cascade = [CascadeType.PERSIST, CascadeType.MERGE])
private val _users = mutableSetOf<User>()
override val users get() = _users

这将创建联接表,但它称为groups__users(双下划线),外键列称为_user_id。在匹配的User类中,我还必须使该属性引用backing属性,例如:@ManyToMany(mappedBy="_users")

我尝试在后备属性上使用@Column(name="user"),它似乎被忽略了。

为什么实际属性不生成联接表?

:: UPDATED ::

看来问题的原因在于在方法而不是字段上使用注释。一个更简单的测试用例:

@Entity
class TestEntity {

    @Id
    @GeneratedValue
    private val id: Long? = null

    @OneToMany
    private val otherEntity: Set<OtherEntity> = setOf()

}

这将按预期生成联接表。但是,这不是:

@Entity
class TestEntity {

    @Id
    @GeneratedValue
    private val id: Long? = null

    @OneToMany
    fun getOtherEntity(): Set<OtherEntity> {
        return emptySet()
    }
}

据我了解,这些应该等效吗?该示例很好地演示了该问题,因为在原始示例中,使用@get:OneToMany显然将注释放在了生成的get方法上。

我对这些注释或Hibernate的理解有问题吗?

1 个答案:

答案 0 :(得分:0)

好的,所以我认为这是Kotlin的问题,但是当我用Java编写代码时发现同样的问题。最终,我发现您不能混合使用Hibernate的字段和方法注释。

在文档(RTFM ...)中:

  

2.2.2.2. Access type

     

默认情况下,类的访问类型   等级由位置定义   @Id或@EmbeddedId批注。   如果这些注释在字段上,   那么仅考虑字段   持久性和状态被访问   通过现场。如果有注释   在吸气剂上,然后只有吸气剂   被认为具有持久性,   状态通过   吸气剂/设定器。那在   练习并推荐   方法。

     
    

注意

         

注释在类层次结构中的位置必须一致     (无论是在字段上还是在财产上)     能够确定默认访问权限     类型。建议坚持     一个注解放置     整个策略     应用。

  

对于我的特定问题,在Kotlin中使用backing属性,然后必须使用@Access注释,如下所示:

@Transient
private val _users = mutableSetOf<User>()
@get:ManyToMany(cascade = [CascadeType.PERSIST, CascadeType.MERGE])
@get:Access(AccessType.PROPERTY)
override val users get() = _users

private fun setUsers(users: Set<User>) {...}

不幸的是,这意味着我必须实现一个私有的setter。

相关问题