Spring JPA无法在Kotlin数据类中使用自定义setter映射字段

我有一个自定义setter的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和login作为单独的列,因为它们都不是@Transient。 我相信你的问题出现在这里,因为你已经标记了_login属性映射到列“登录”,而登录属性没有@Column批注,所以它试图映射到它的默认值“登录”已经有_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方法为您做保存到数据库之前的小封面。