kotlin: не может получить подтверждение аннотации api

========== ========== UPDATE

когда я изменяю аннотацию на @get: NotNull, @get: Min и @get: Max, hibernate-validator может прочитать эти успехи аннотаций.

Но я все еще хочу знать:

почему аннотация validation-api, такая как @NotNull, @Min и @Max, не может использоваться непосредственно для членов класса данных, в то время как аннотации JPA могут быть ????

========== Ниже приведен исходный вопрос ===========

когда я пытался использовать аннотацию validation-api для класса данных, класс Validator (из hibernate-validator) не может получить аннотации, поэтому проверка не прошла.

я написал тестовый пример, который включает 3 класса данных:

  • 1-й вариант использует аннотацию JPA @Column и @Id, которая может быть успешно прочитана тестовым случаем.
  • Вторая используется для проверки валидации-api @NotEmpty, @ Min, @ Max для членов, эта аннотация не может быть прочитана тестовым случаем
  • В-третьих, используйте validation-api annotation @get: NotEmpty, @get: Min, @get: Max, тестовый пример не может прочитать эти аннотации.

Цель и сохранение @Column, @NotNull, @Min и @Max – все: RUNTIME и FIELD

Итак, что случилось взади? как я могу правильно использовать аннотации проверки?

вот тестовый пример:

import org.hibernate.validator.constraints.NotEmpty import org.junit.Test import javax.persistence.Column import javax.persistence.Id import javax.validation.constraints.Max import javax.validation.constraints.Min import kotlin.reflect.KFunction import kotlin.reflect.KProperty import kotlin.reflect.jvm.javaField import kotlin.reflect.jvm.javaMethod class KotlinFeatureTest2 { @Test fun test_get_annotation() { // can get field's annotation for BeanUseJPAAnnotation success println("Getting field annotations for BeanUseJPAAnnotation :") BeanUseJPAAnnotation::class.members.forEach { if (it is KProperty) { val field = it.javaField println("${field?.name}'s annotations:") field?.annotations?.forEachIndexed { i, an -> println(" $i is: $an") } } } println("--------------------") println("Getting field annotations for BeanUseValidationAnnotation :") // CANT get field's annotation for BeanUseJPAAnnotation success BeanUseValidationAnnotation::class.members.forEach { if (it is KProperty) { val field = it.javaField println("${field?.name}'s annotations:") field?.annotations?.forEachIndexed { i, an -> println(" $i is: $an") } } } println("--------------------") println("Getting field annotations for BeanUseValidationAnnotationOnMethod :") // CANT get field's annotation for BeanUseJPAAnnotation success BeanUseValidationAnnotationOnMethod::class.members.forEach { if (it is KFunction) { val method = it.javaMethod println("${method?.name}'s annotations: ") method?.annotations?.forEachIndexed { i, an -> println(" $i is: $an") } } } } } data class BeanUseJPAAnnotation( @Column(name = "id") @Id val id: String, @Column(name = "user_name") val name: String) data class BeanUseValidationAnnotation( @NotEmpty(message = "name can not be empty") val name: String, @Min(value = 1) @Max(value = 100) val age: Int ) data class BeanUseValidationAnnotationOnMethod( @get:NotEmpty(message = "name can not be empty") val name: String, @get:Min(value = 1) @get:Max(value = 100) val age: Int) 

и вот вывод этого тестового примера:

 Getting field annotations for BeanUseJPAAnnotation : id's annotations: 0 is: @javax.persistence.Column(nullable=true, unique=false, precision=0, name=id, length=255, scale=0, updatable=true, columnDefinition=, table=, insertable=true) 1 is: @javax.persistence.Id() name's annotations: 0 is: @javax.persistence.Column(nullable=true, unique=false, precision=0, name=user_name, length=255, scale=0, updatable=true, columnDefinition=, table=, insertable=true) -------------------- Getting field annotations for BeanUseValidationAnnotation : age's annotations: name's annotations: -------------------- Getting field annotations for BeanUseValidationAnnotationOnMethod : component1's annotations: component2's annotations: copy's annotations: equals's annotations: hashCode's annotations: toString's annotations: 

Ниже приведена сигнатурная часть javax.persistence.Column :

 @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Column { 

Напротив, вот та же самая часть javax.validation.constraints.Min :

 @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) @Repeatable(List.class) @Documented @Constraint(validatedBy = { }) public @interface Min { 

Поскольку вы видите, что аннотации JPA Persistence нацелены на METHOD и FIELD значит, Kotlin испускает их на уровне FIELD . Однако аннотации API валидаторов нацелены на большее количество конструктов, в частности, PARAMETER . Учитывая, что при создании аннотаций для объявленных свойств конструктора компилятор Kotlin выбирает только аннотировать параметры . BeanUseValidationAnnotation эквивалента конструктора BeanUseValidationAnnotation в Java будет выглядеть так:

 public BeanUseValidationAnnotation(@NotEmpty(message = "name can not be empty") @NotNull String name, @Min(1L) @Max(100L) int age) { 

Такое поведение указано в документации :

Если вы не укажете цель использования сайта, цель будет выбрана в соответствии с аннотацией @Target используемой аннотации. Если имеется несколько применимых целей, используется первая применимая цель из следующего списка:

  • param
  • property
  • field