Spring JPA не может отображать поле с пользовательским сеттером в классе данных Kotlin

У меня есть класс данных Kotlin с пользовательским сеттером. Рамка Spring JPA не может отображать свойство с помощью настраиваемого сеттера. Если я удалю пользовательский getter / setter и переименуют свойство для login вместо _login , все, кажется, работает нормально. Как я могу создать свойство в классе данных Kotlin с помощью настраиваемого сеттера, чтобы он был распознан в рамках JPA?

User.kt

 @Entity @Table(name = "jhi_user") @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) data class User ( @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @SequenceGenerator(name = "sequenceGenerator") var id: Long? = null, @NotNull @Pattern(regexp = Constants.LOGIN_REGEX) @Size(min = 1, max = 50) @Column(name = "login", length = 50, unique = true, nullable = false) var _login: String? = null, @JsonIgnore @NotNull @Size(min = 60, max = 60) @Column(name = "password_hash",length = 60) var password: String? = null, ... @JsonIgnore @ManyToMany @JoinTable( name = "jhi_user_authority", joinColumns = arrayOf(JoinColumn(name = "user_id", referencedColumnName = "id")), inverseJoinColumns = arrayOf(JoinColumn(name = "authority_name", referencedColumnName = "name"))) @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) @BatchSize(size = 20) var authorities: MutableSet<Authority>? = null): AbstractAuditingEntity(), Serializable { //Lowercase the login before saving it in database var login: String? get() = _login set(value) { _login = StringUtils.lowerCase(value, Locale.ENGLISH) } } 

Ошибка, которую я получаю:

 ... Caused by: java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [login] on this ManagedType [com.sample.domain.AbstractAuditingEntity] at org.hibernate.metamodel.internal.AbstractManagedType.checkNotNull(AbstractManagedType.java:128) at org.hibernate.metamodel.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:113) at org.hibernate.metamodel.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:111) at org.springframework.data.jpa.repository.query.QueryUtils.toExpressionRecursively(QueryUtils.java:569) at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.getTypedPath(JpaQueryCreator.java:377) at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.build(JpaQueryCreator.java:300) at org.springframework.data.jpa.repository.query.JpaQueryCreator.toPredicate(JpaQueryCreator.java:205) at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:117) at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:54) at org.springframework.data.repository.query.parser.AbstractQueryCreator.createCriteria(AbstractQueryCreator.java:111) at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:90) at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:78) at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.<init>(PartTreeJpaQuery.java:135) at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$CountQueryPreparer.<init>(PartTreeJpaQuery.java:256) at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:72) at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:103) 

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

Для начала JPA захочет зарегистрировать как _login, так и логин как отдельные столбцы в вашей базе данных, так как ни один из них не является @Transient. Я считаю, что ваша проблема возникает здесь, так как вы отметили свойство _login для сопоставления с столбцом «login», тогда как свойство login не имеет аннотации @Column, поэтому оно пытается сопоставить его значение по умолчанию «login», у которого уже есть свойство _login сопоставлен с ним.

Поэтому я думаю, вы, вероятно, захотите сделать _login переходным процессом и только сохранить логин (я пропустил ненужный код для краткости и ясности):

 ... @Transient var _login: String? = null, ... @NotNull @Pattern(regexp = Constants.LOGIN_REGEX) @Size(min = 1, max = 50) @Column(name = "login", length = 50, unique = true, nullable = false) var login: String? get() = _login set(value) { _login = StringUtils.lowerCase(value, Locale.ENGLISH) } 

Если это все еще не работает, я действительно думаю, что это больше хлопот, чем стоит попытаться получить это уже слегка взломанное обходное решение для использования пользовательских настроек для свойств конструктора, работающих с JPA. Я бы предложил вместо этого использовать метод @ PrePersist / @ PreUpdate, чтобы сделать нижнюю шкалу для вас до ее сохранения в базе данных.