1. ホーム
  2. java

[解決済み] Lombokを使用したSuperBuilderによる親クラスの拡張

2022-02-28 18:42:31

質問

しかし、いくつかの要件により、DTOを以下のような親クラスに拡張する必要があります。

DTOの前。

@Getter
@ToString
@EqualsAndHashCode
@Builder(toBuilder = true)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class RequestMessage {
private final String name;
 }

拡張が必要な親クラス

   @Data
   @SuperBuilder(toBuilder = true)
   @JsonDeserialize(builder = MyDTO.Builder.class)
   public abstract class MyDTO implements Serializable {
   @JsonIgnore private final ObjectMapper objectMapper = new ObjectMapper();
   protected String myAccountId;

   protected MyDTO() {}

   public static int hashCode(Object... objects) {
     return Arrays.deepHashCode(objects);
   }

   public static boolean equal(Object o1, Object o2) {
    // implementation of equals method
   }

   public abstract String emitSerializedPayload() throws JsonProcessingException;

   @JsonPOJOBuilder(withPrefix = "")
   protected abstract static class Builder<T extends MyDTO, B extends Builder<T, B>> {
   protected T dtoInstance;
   protected B builderInstance;

   public Builder() {
  dtoInstance = createDtoInstance();
  builderInstance = returnBuilderInstance();
}

protected abstract T createDtoInstance();

protected abstract B returnBuilderInstance();

public B myAccountId(String accountId) {
  dtoInstance.myAccountId = accountId;
  return builderInstance;
}

public T build() {
  return dtoInstance;
}
}
}

しかし、私のアプリケーションには多くのクラスがあり、それらを手動で変更したくありません。既存のRequestMessageクラスをアノテーションまたは動作させるための最小限の変更で変更するにはどうすればよいですか?

これは私が試したものですが、私はこれを行う際にコンパイルエラーが表示されます。

    RequestMessage.Builder().name(myName).myAccountId(myAcId).build();
     
     

私が試したのは、以下のようなものです。

 @Getter
 @ToString
 @EqualsAndHashCode(callSuper = true)
 @SuperBuilder(toBuilder = true)
 @AllArgsConstructor(access = AccessLevel.PRIVATE)
 public class RequestMessage extends MyDTO {
 private final String name;

 @Override
 public String emitSerializedPayload() throws JsonProcessingException {
// TODO Auto-generated method stub
return null;
}
} 
 

解決方法は?

lombokを混在させるべきではありません @Builder を静的なインナーBuilderクラスで使用することができます。もし Builder クラスがあれば、次のコードはうまくいくはずです。

リクエストメッセージ :

@Getter
@ToString
@EqualsAndHashCode(callSuper = true)
@SuperBuilder(toBuilder = true)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class RequestMessage extends MyDTO {
    private final String name;

    @Override
    public String emitSerializedPayload() throws JsonProcessingException {
    return null;
    }
    public RequestMessage(String myAccountId, String name) {
        super(myAccountId);
        this.name = name;
}
}

マイDTO :

@Data
@SuperBuilder(toBuilder = true)
public abstract class MyDTO implements Serializable {
    @JsonIgnore private final ObjectMapper objectMapper = new ObjectMapper();
    protected String myAccountId;

    protected MyDTO() {}

    public MyDTO(String myAccountId) {
       this.myAccountId = myAccountId;
    }

    public static int hashCode(Object... objects) {
        return Arrays.deepHashCode(objects);
    }

    public static boolean equal(Object o1, Object o2) {
        // implementation of equals method
        return false;
    }
    public abstract String emitSerializedPayload() throws JsonProcessingException;
}

テスト :

@Test
void name() {
    String myName = "myName";
    String myAccountId = "myAccountId";
    var request = RequestMessage.builder().name(myName).myAccountId(myAccountId).build();
    System.out.println("request = " + request);
    RequestMessage requestMessage = new RequestMessage(myAccountId, myName);
}