kotlin 数据类 + bean 验证 jsr 303 [英] kotlin data class + bean validation jsr 303

查看:43
本文介绍了kotlin 数据类 + bean 验证 jsr 303的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让 Kotlin 在 spring-data-rest 项目中使用 jsr 303 验证.

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

给定以下数据类声明:

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

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

@Size 注释在这里没有任何作用,使我能够保存名称为 1 个字符的用户.
当在 Java 类而不是 Kotlin 中执行相同的示例时,它运行良好.

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 问题.

This makes me think of a Kotlin problem.

预先感谢您的帮助!

推荐答案

您需要使用 注解使用目标,因为在构造函数中声明的属性的默认值是针对构造函数参数上的注解而不是getterstrong>(JavaBeans 兼容主机会看到)当有多个选项可用时.此外,在此处使用 data 类可能不合适(请参阅末尾的注释).

You need to use Annotation use-site targets since the default for a property declared in the constructor is to target the annotation on the constructor parameter instead of the getter (which will be seen by JavaBeans compliant hosts) when there are multiple options available. Also using a data class might be inappropriate here (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
)

Kotlin 文档中的 property 目标可能看起来很诱人,但它只能从 Kotlin 而不是 Java 中看到.通常 get 可以解决问题,bean set 不需要它.

The property 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.

文档将过程描述为:

如果不指定使用站点目标,则根据正在使用的注解的@Target注解选择目标.如果有多个适用目标,则使用以下列表中的第一个适用目标:

If you don’t specify a use-site target, the target is chosen according to the @Target annotation of the annotation being used. If there are multiple applicable targets, the first applicable target from the following list is used:

  • 参数
  • 财产
  • 字段

@Size 注释是:

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

因此,由于 PARAMETER 是一个有效的目标,并且有多个目标可用(参数、字段、方法 [get/set])它选择了 PARAMETER 这不是你的想.因此,对于要查看属性的 JavaBean 主机,它将查找 getter(属性由 getter/setter 定义,而不是由支持字段定义).

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 property it will look for the getter (properties are defined by the getter/setter and not the backing field).

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

In one of the Java samples, it shows:

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

    // ...

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

    // ...
}

这符合我们在 getter 上使用它的用法.如果它像某些验证注释显示的那样在字段上,请参阅 field 使用站点目标.或者,如果该字段也必须可公开访问,请参阅 @Kotlin 中的 JvmField 注释.

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.

注意: 正如在其他人的注释中提到的,如果实体使用一个自动生成的 ID,因为它不会像检索到的对象一样存在于新对象中;data 类将生成 equalshashCode 以包含所有字段,包括不应该包含的字段.您可以从 休眠文档.

NOTE: As mentioned in notes from others, you should likely consider NOT using a data 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 data class will generate equals and hashCode to include all fields including the ones it should not. You can read guidance about this from the Hibernate docs.

这篇关于kotlin 数据类 + bean 验证 jsr 303的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆