I'm trying to get Kotlin working with jsr 303 validation on a spring-data-rest project.

Given the following data class declarartion :

@Entity data class User(
    @Id 
    @GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
    var id: Long? = null,

    @Size(min=5, max=15)
    val name: String
)

The @Size annotation has no effect here, making me able to save a user with a name of 1 character.
It works well when executing the very same example but in a Java class instead of Kotlin.

这让我想到了Kotlin 的问题.

提前感谢您的帮助!

推荐答案

您需要使用Annotation use-site targets,因为当有多个选项可用时,构造函数中声明的属性的默认目标是构造函数parameter上的注释,而不是getter(兼容JavaBeans的主机将看到getter).在这里使用data类也可能不合适(see note at end).

@Entity data class User(
    @Id
    @GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
    var id: Long? = null,

    @get:Size(min=5, max=15) // added annotation use-site target here
    val name: String
)

The 所有物 target from the Kotlin docs may look tempting, but it can only be seen from Kotlin and not Java. Usually get does the trick, and it is not needed on the bean set.

The docs describe the process as:

如果未指定使用站点目标,则将根据所用注释的@target注释 Select 目标.如果存在多个适用目标,则使用以下列表中的第一个适用目标:

  • param
  • 所有物
  • field

And the @Size annotation is:

@Target(value={METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER})

Therefore since PARAMETER is a valid target, and multiple targets are available (parameter, field, method [get/set]) it choses PARAMETER which is not what you want. Therefore for a JavaBean host to see the 所有物 it will look for the getter (properties are defined by the getter/setter and not the backing field).

在其中一个Java samples个例子中,它显示:

public class Book {
    private String title;
    private String description;

    // ...

    @NotEmpty(groups={FirstLevelCheck.class, Default.class})
    @Size(max=30)
    public String getTitle() {
        return title;
    }

    // ...
}

Which matches our usage of having it on the getter. If it were to be on the field like some of the validation annotations show, see the field use-site target. Or if the field must also be publicly accessible, see the @JvmField annotation in Kotlin.

NOTE: As mentioned in notes from others, you should likely consider NOT using a 101 class for entities if they use an auto-generated ID since it will not exist for new objects the same as for retrieved objects; and a 101 class will generate 103 and 104 to include all fields including the ones it should not. You can read guidance about this from the 100.

Kotlin相关问答推荐

Mockk:对同一函数进行两次存根会忽略第一个行为

测试协程和线程之间的差异,我在kotlin中使用线程时无法得到OOM错误

有没有一种简单的方法可以将数组/列表中的每个元素相互相乘 - Kotlin?

kotest 更改环境变量

Saripaar formvalidation 在 kotlin 中第二次不起作用

为什么 IntelliJ Idea 无法识别我的 Spek 测试?

无法删除部分子项.这可能是因为进程打开了文件或将其工作目录设置在目标目录中

Kotlin 枚举中的循环引用

DatabaseManager_Impl 不是抽象的,不会覆盖 RoomDatabase 中的抽象方法 clearAllTables()

Kotlin Compose,在行中对齐元素

主机名不能为空

如何在MVVM架构中观察RecyclerView适配器中的LiveData?

哪里可以找到aapt2日志(log)?

如果我可以将 Flow 和 StateFlow 与生命周期范围 \ viewLifecycleOwner.lifecycleScope 一起使用,那么在 ViewModel 中使用 LiveData 有什么意义

Kotlin:sealed class cannot "contain" data classes?

如何让数据类在Kotlin中实现接口/扩展超类属性?

Kotlin中的属性(properties)和参数(parameters)有什么区别?

在 kotlin 中,如何将主构造函数中的属性设置器设为私有?

如何计算Kotlin中的百分比

将字符串转换为HashMap的最简单方法