我有一个Job类,看起来像这样:

@Entity
@Table
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Data
@NoArgsConstructor
public class Job implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Column(nullable = false)
    private String job;

    @ManyToOne
    @JsonIgnoreProperties("jobs")
    private Job next;



和创建作业的方法:

    @PostMapping("/jobs")
    public ResponseEntity<Job> createJob(@Valid @RequestBody Job job) throws URISyntaxException {
        Job result = jobRepository.save(job);
        return ...
    }


一切正常,直到这里。现在,将@AllArgsConstructor添加到Job类会导致MismatchedInputException。

Bad Request: JSON parse error: Cannot construct instance of `xxx.domain.Job` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `xxx.domain.Job` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)


我试图将lombok.anyConstructor.addConstructorProperties = true添加到lombok.config文件中,如我发现的答案中所述。但这只会导致以下错误:

[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ project-name ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 27 source files to /path/target/test-classes
Unknown key 'lombok.anyConstructor.addConstructorProperties' (/path/lombok.config:2)


我尝试使用旧版本的lombok,因为我发现一些github问题解决了更新lombok时出现的问题。此外,也没有成功(尝试1.16.18版)

我也尝试删除private Job next属性,该属性使代码正常工作而没有任何错误。因此,这一定是一个问题吗?

最佳答案

摘要

您可能不想要任何形式的@ConstructorProperties

由于不幸的原因,键lombok.anyConstructor.addConstructorProperties = true不再可用。右键是lombok.anyConstructor.suppressConstructorProperties = false,尽管您可能不想实际应用此配置键。

解决方法可能是更新构建工具,以告诉javac在类文件中生成参数名称信息。

你不要@ConstructorProperties

@ConstructorProperties批注的“点”有两个方面:允许运行时代码(使用反射API的Java代码)检查构造函数的参数名称,并允许编译时工具找出名称。构造函数的所有参数(如果全部可用)是已编译(类)文件,而不是源(java)文件。

但是,出于此目的,@ConstructorProperties已过时。如今,大多数编译器配置已默认更新为在类文件中包含参数名称,并且反射API已更新为您提供了一种轻松的方法。例如:

public class Example {
    public Example(String a, int b) {}
    public static void main(String[] args) throws Exception {
        System.out.println(Example.class
            .getConstructor(String.class, int.class)
            .getParameters()[1]
            .getName());
    }
}


然后在命令行上:

javac Example.java
java Example
arg1

javac -parameters Example.java
java Example
b


您可能希望将上述源文件包含在构建中作为快速检查,以确保使用任何用于构建源文件的构建系统来设置-parameters选项。它应该打印b,如果没有打印(如果打印arg1),请快速搜索如何在编译过程中制作maven或gradle或任何相关的发出参数名称信息。

现在,杰克逊有机会仅使用此信息(而不是依赖@ConstructorProperties)。我实际上不知道是否这样做,但是我会假设这样:这是“新的”方式。

为什么你不想要它

...因为历史证明,Java社区不能被它所信任。

批注最初是一个简单,清晰的设计(您可以使用它来以批注形式传递参数名称),并且几乎立即,整个社区陷入混乱:如果使用此批注,则android和GWT都将拒绝编译您的代码甚至在您的Java文件中。

然后,过了一会儿,一切都很好,并且可以在.java扩展名结尾的文件中可行地编译代码的所有内容的所有最新版本,至少都将默默地忽略此注释。

但是后来带有模块系统的java9出现了,并且以oracle的无限智慧,他们决定....将此注释推入...... java.desktop模块???到目前为止,我完全不知道那里发生了什么,因为这似乎是一个非常不合适的模块。但是,这确实意味着,如果要在模块化构建中以任何形式使用ConstructorProperties(即,任何在根目录中具有module-info.java文件的内容),则需要向其中添加requires java.desktop;,除非这可能暗示某些事情。毫无意义(例如:您的模块不能在无头JVM上运行)。

这有两点:[1]为什么构造函数属性的lombok配置和行为如此混乱,以及[2]为什么我建议您不要使用@ConstructorProperties

龙目岛的配置

如果不管上面的建议如何,您确实要使用ConstructorProperties,那么在lombok中正确的配置是:

lombok.anyConstructor.suppressConstructorProperties = false


由于上述历史,lombok中用于生成@ConstructorProperties的配置键有些不幸。对于给您带来的困难,我深表歉意。 (我是龙目岛的核心贡献者)。

最初,存在addConstructorProperties(与之相比要简单得多:总是生成此批注,并且根本没有配置密钥),因为android和GWT无法处理它的存在,并且据我们估计,更多的人使用android / GWT + lombok ,而不是依赖于生成@ConstructorProperties的人,因此,我们认为适当的默认行为应该是在生成构造函数时不包括注释。

然后,当GWT / Android解决此问题时,力量的平衡发生了变化:我们现在意识到,“默认情况下生成它”更有助益而不是伤害。我们确实确实希望属性始终“默认为false”,因此,我们将键重命名为lombok.anyConstructor.suppressConstructorProperties

然后,在甚至更高版本的lombok中,放弃了“我们希望所有事物默认为false”的格言之后,我们将默认行为改回了原来的样子:默认情况下不生成ConstructorProperties。这样做很对,如果使用模块化构建,由于注释放在java.desktop模块中,因此导致代码根本无法编译。尽管整个Java社区继续在很大程度上避免使用拼图游戏,但仍有一些人确实使用了拼图游戏,足以将力量平衡转移回去。此外,我们现在很清楚,@ConstructorProperties作为一种机制已经注定要失败,而-parameters切换正确,麻烦的解决方案。

我们期望龙目岛的行为不会第三次改变。

10-01 14:15