Hibernate не создает таблицу соединений для свойства Kotlin со свойством backing - PullRequest
0 голосов
/ 03 января 2019

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

Полученная таблица имеет столбцы name и id, как и ожидалось, но она не создает ожидаемую таблицу соединения (groups_users). Если я удалю свойство backing и просто сделаю users нормальным свойством, оно будет работать как положено.

Я также пытался сделать @get:@ManyToMany... для свойства, это не имеет никакого эффекта.

Если вместо этого я добавлю аннотацию к вспомогательному свойству:

@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") в свойстве backing, похоже, оно игнорируется.

Почему фактическое свойство не генерирует таблицу соединений?

:: ОБНОВЛЕНО ::

Кажется, причиной проблемы является использование аннотации для методов, а не для полей. Более простой тестовый пример:

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

Что-то не так с моим пониманием этих аннотаций или спящего режима?

1 Ответ

0 голосов
/ 04 января 2019

ОК, так что я подумал, что это проблема Kotlin, но обнаружил, что у меня была такая же проблема, когда я писал это на Java. В конце концов я обнаружил, что вы не можете смешивать аннотации полей и методов для Hibernate.

Это в документации (RTFM ...):

2.2.2.2. Тип доступа

По умолчанию тип доступа класса иерархия определяется положением аннотаций @Id или @EmbeddedId. Если эти аннотации на поле, тогда только поля рассматриваются для настойчивость и состояние доступно через поле. Если есть аннотации на добытчик, то только добытчики считаются для настойчивости и состояние доступно через геттер / сеттер. Это хорошо работает в практика и рекомендуется подход.

Примечание

Размещение аннотаций в иерархии классов должно быть согласованным (либо поле, либо свойство) возможность определить доступ по умолчанию тип. Рекомендуется придерживаться одно размещение аннотации стратегия на протяжении всего вашего применение.

Для моей конкретной проблемы, используя свойство поддержки в Kotlin, тогда я должен использовать аннотацию @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>) {...}

К сожалению, это означает, что я должен реализовать частный установщик.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...