========== UPDATE ==========
当我将注释更改为@get:NotNull,@ get:Min和@get:Max时,hibernate-validator可以读取这些注释成功。
但我仍然想知道的是:
为什么验证-api的注释,例如@NotNull,@ Min和@Max不能直接用于数据类的成员,而JPA的注释可以是? ???
==========贝娄是原产地问题===========
当我尝试在数据类上使用validation-api的注释时,Validator类(来自hibernate-validator)无法获取注释,因此验证失败。
我写了一个测试用例,其中包括3个数据类:
@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:
答案 0 :(得分:2)
以下是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持久性注释定位METHOD
和FIELD
因此Kotlin会在FIELD
级别上发出它们。然而,验证器API注释针对更多构造,特别是PARAMETER
。鉴于在为构造函数声明的属性生成注释时,Kotlin编译器选择仅注释参数。 Java中等效的BeanUseValidationAnnotation
构造函数签名如下所示:
public BeanUseValidationAnnotation(@NotEmpty(message = "name can not be empty") @NotNull String name, @Min(1L) @Max(100L) int age) {
此行为已声明为in the documentation:
如果未指定使用地点目标,则根据目标选择目标 到正在使用的注释的
@Target
注释。如果有 多个适用的目标,第一个适用的目标来自 使用以下列表:
param
property
field