2017-08-14 20 views
1

私はカスタムセッターでKotlinデータクラスを持っています。 SpringのJPAフレームワークはカスタムセッターでプロパティをマッピングするようには見えません。私がカスタムgetter/setterを削除しての代わりにloginにプロパティの名前を変更すると、すべて正常に動作しているようです。 JPAフレームワークで認識されるように、カスタムセッターでKotlinデータクラスのプロパティを作成するにはどうすればよいですか?Spring JPAはKotlinデータクラスのカスタムセッターでフィールドをマップできません

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) 
+0

カスタムgetter/setterはどういう意味ですか? –

+0

@AbdullahKhanコードサンプルの最後の2行は小文字の 'login'変数を設定しています。私はこれを行うためにカスタムセッターを使用する必要があります。 – Jerry

答えて

2

は、私が知っビット醜い(残念ながら唯一の方法でありますしている)。

はじめにJPAはどちらも@Transientではないため、データベースに別の列として_loginとloginの両方を登録したいと考えています。私はloginのプロパティに@Columnアノテーションがないのに対し、_loginプロパティを "login"カラムにマッピングするために_loginプロパティをマークしているので、あなたの問題が発生すると思います。そのため、すでに_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メソッドを使用して、データベースに保存する前にlowercaseを行うことをお勧めします。

+0

私はsetterで '_login'の代わりに' field'パラメータを使うようにコードを変更しなければなりませんでした。すべての私のテストは今通り抜けているようです。 setterで 'field'プロパティと' _login'を使用する違いは何ですか? – Jerry

+0

@Jerry ohありがとう私はそれを見つけなかった。 _loginを使用しようとすると、setterでフィールドパラメータを使用する必要があります。_loginのデフォルトゲッターへの再帰呼び出しが発生します(https://medium.com/@agrawalsuneet/backing-field-in-kotlin- bd9c2d5b6da5) – Plog

関連する問題