【问题标题】:Explicit constructor using Lombok?使用 Lombok 的显式构造函数?
【发布时间】:2011-04-21 08:00:02
【问题描述】:

我正在重写一些管理数据库的杂乱代码,并看到原始程序员创建了一个映射到数据库的类,如下所示:

(我已经删除了对这个问题没有意义的不必要的代码)

@Entity
@Data
@EqualsAndHashCode(callSuper = false, of = { "accessionCode", "header", "date" })
@SuppressWarnings("PMD.UnusedPrivateField")
public class PDBEntry implements Serializable {
    @Id
    @NaturalId
    @NotEmpty
    @Length(max = 4)
    private String accessionCode;

    @NaturalId
    @NotEmpty
    private Date date;

    @NaturalId
    // We allow for the header to be 'null'
    private String header;

    private Boolean isValidDssp;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdated = new Date(System.currentTimeMillis());

    protected PDBEntry(){}

    public PDBEntry(String accessionCode, String header, Date date){
        this.accessionCode = accessionCode;
        this.header = header;
        this.date = date;
    }
}

我仍然是 Hibernate 的初学者并使用 Lombok,但这不会做同样的事情,Lombok 不会自动为您创建所需的构造函数吗?

@Entity
@Data
@SuppressWarnings("PMD.UnusedPrivateField")
public class PDBEntry implements Serializable {
    @Id
    @NaturalId
    @NotEmpty
    @NonNull
    @Length(max = 4)
    private String accessionCode;

    @NaturalId
    @NotEmpty
    @NonNull
    private Date date;

    @NaturalId
    // We allow for the header to be 'null'
    private String header;

    private Boolean isValidDssp;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdated = new Date(System.currentTimeMillis());
}

此外,这段代码的原始程序员说他允许标头为“空”,但他明确创建了一个需要标头值的构造函数。是我遗漏了什么还是有点矛盾?

【问题讨论】:

    标签: java hibernate lombok


    【解决方案1】:
    @NoArgsConstructor, 
    @RequiredArgsConstructor, 
    @AllArgsConstructor
    

    生成不带参数、每个最终/非空字段一个参数或每个字段一个参数的构造函数。阅读此lombok-project

    @Data
    @RequiredArgsConstructor /*Duplicate method Someclass() in type Someclass*/
    @NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)  /*Duplicate method Someclass() in type Someclass*/
    @Entity
    public class Someclass {      
        @Id
        private  String id;
        private  String name;
        private  Type type; 
    
        public static enum Type { X , Y, Z}
    }
    

    通过将成员变量设为 final 来修复它

    @Data
    @RequiredArgsConstructor 
    @NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
    @Entity
    public class Someclass {
    
        @Id
        private final String id;
        private final String name;
        private final Type type; 
        public static enum Type { X , Y, Z}
    }
    

    【讨论】:

      【解决方案2】:

      如果您使用带有@NonNull 字段的@Data 并且仍然想要一个noargs-constructor,您可能想尝试将所有3 个注释一起添加

      @NoArgsConstructor
      @RequiredArgsConstructor
      @AllArgsConstructor
      

      显然是我在 Eclipse Kepler 和 lombok v0.11.4 中复制的一个旧的 intelliJ 错误

      【讨论】:

        【解决方案3】:

        看看@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor

        @Data 的构造函数行为类似于@RequiredArgsConstructor

        @RequiredArgsConstructor 生成一个 每个构造函数有 1 个参数 需要特殊处理的字段。 所有最终字段都有一个参数,如 以及标记为的任何字段 @NonNull 未在哪里初始化 它们被声明了。

        鉴于您的所有字段都不是final@NonNull,这将导致无参数构造函数。但是,这并不是实现此行为的最有表现力的方式。

        在这种情况下,您可能想要的是 @NoArgsConstructor(可选地与 @AllArgsConstructor 结合使用),以清楚地传达预期的行为,如文档中所述:

        某些 java 结构,例如 hibernate 和服务提供者 接口需要无参数 构造函数。这个注释很有用 主要结合任一 @Data 或其他构造函数之一 生成注释。

        【讨论】:

        • 是的,我读到了@RequiredArgsConstructor,但由于它在@Data 中是标准的,所以我没有添加它。我的问题是我是否正确使用了注释,因为原始程序员确实使用了 Lombok 但没有使用 @NonNull 注释,而是使用了显式构造函数。你说我的字段都不是@NonNull,但仔细查看我的代码(第二个框),我用@NonNull 注释了accessionCode 和日期字段。现在,由于 Hibernate 确实似乎需要一个无参数的构造函数,这会是一个好的风格吗? @Data @NoArgsConstructor(access = AccessLevel.PROTECTED) @RequiredArgsConstructor
        • 好的,对于那些也开始使用 Lombok 的人来说,我刚刚听说 @RequiredArgsConstructor 不是很健壮,它需要你类中的字段顺序来构建构造函数,所以如果其他人更改了此顺序,您的调用构造函数的代码停止工作,因此结果证明显式构造函数仍然是更好的选择。但是,如果您使用 Hibernate,@NoArgsConstructor(access = AccessLevel.PROTECTED) 似乎确实很有用。谢谢大家的帮助。
        • @FinalArt2005 但问题不在于@RequiredArgsConstructor,而在于程序员做这些有趣的事情。任何人都不应该在不知道具体内容的情况下更改外国代码中的内容。请注意,即使使用纯 Java,它也可能会失败(初始化程序的顺序)。请注意,它会不必要地污染 VCS 中的历史记录。
        【解决方案4】:

        那一点是矛盾的,你是对的。我以前没有使用过 Lombok,但是如果你想能够创建一个 bean 并坚持使用 hibernate,那么据我所知,你需要上面给出的默认构造函数。它使用 Constructor.newInstance() 来实例化新对象。

        这里有一些更详细的休眠文档。

        Hibernate Documentation

        【讨论】:

        • 据我所知,类 def 正上方的 @Data 注释将创建这个默认构造函数,并且据我所知,字段上方的 @NonNull 注释将导致 Lombok 制作这些该构造函数中的字段参数,以便您必须为它们提供值,并且还将检查它们是否为空。但由于我是新手,我想知道是我自己还是原来的程序员在这里犯了一些小错误。
        猜你喜欢
        • 2020-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-14
        • 1970-01-01
        • 1970-01-01
        • 2019-03-28
        相关资源
        最近更新 更多