【问题标题】:kotlin data class + bean validation jsr 303kotlin 数据类 + bean 验证 jsr 303
【发布时间】:2016-06-21 05:46:39
【问题描述】:

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

给定以下数据类声明:

@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 中时,它运行良好。

这让我想到了一个 Kotlin 问题。

提前感谢您的帮助!

【问题讨论】:

  • 注解的目标应该是什么?构造函数参数还是字段?

标签: jpa bean-validation kotlin spring-data-rest data-class


【解决方案1】:

您需要使用Annotation use-site targets,因为在构造函数中声明的属性的默认值是针对构造函数parameter上的注释而不是getter(这将当有多个选项可用时,符合 JavaBeans 的主机可以看到。此外,在这里使用 data 类可能不合适(请参阅末尾的注释)。

@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 不需要它。

文档将过程描述为:

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

  • 参数
  • 财产
  • 字段

@Size注解是:

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

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

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;
    }

    // ...
}

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

注意: 正如其他人的笔记中提到的,如果实体使用自动生成的 ID,您可能应该考虑不要为实体使用 data 类因为它不会像检索到的对象一样存在于新对象中; data 类将生成 equalshashCode 以包含所有字段,包括不应包含的字段。您可以从Hibernate docs 阅读有关这方面的指导。

【讨论】:

  • 你摇滚!谢谢 !也可以使用@get:Size(min=5, max=15)注解。
  • 虽然它是正确的答案,但值得注意的是,无论如何您都不应该将data class 用于实体。原因是 - 它将使用所有属性(包括 id)生成 equalshashCode 方法,这不是 JPA 实体所期望的行为。见这里:docs.jboss.org/hibernate/stable/core.old/reference/en/html/…
  • 感谢@waste,我进行了编辑以直接在答案中添加注释。
  • "如果数据类体中有equals()、hashCode()或toString()的显式实现或超类中的最终实现,则这些函数不会生成,现有的实现是使用” - kotlin 文档
  • 天哪,非常感谢您的回答。我花了一天的时间来弄清楚为什么我的注释没有考虑到...
【解决方案2】:

validation annotations 使用@get@field 目标。不支持目标 @param(第一个默认值)和 @property 的注释。

例如:

@NotEmpty@field:NotEmpty

data class Student(
    @field:NotEmpty @field:Size(min= 2, message = "Invalid field") var name: String? = ""
)

GL

【讨论】:

    猜你喜欢
    • 2015-01-10
    • 2013-11-23
    • 1970-01-01
    • 2011-07-24
    • 2011-01-31
    • 2012-05-12
    • 1970-01-01
    • 2012-02-08
    • 2012-03-06
    相关资源
    最近更新 更多