Issue
I have a spring-boot application which uses a mongoDb database to store objects. One of the objects is ExampleDoc as below:
package com.example;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.ToString;
import org.bson.types.ObjectId;
@ToString
@Document
public class ExampleDoc {
@PersistenceConstructor
public ExmapleDoc(ObjectId id,
String uniqueField,
String field1,
String field2) {
this.id = id;
this.uniqueField = uniqueField;
this.field1 = field1;
this.field2 = field2;
}
public ExmapleDoc() {}
@Id
@Getter @Setter @NonNull private ObjectId id;
@Indexed(unique = true)
@Getter @Setter @NonNull private String uniqueField;
@Getter @Setter String field1
@Getter @Setter String field2
}
I am using lombok to instantiate the fields along with their getters and setters. There are currently 2 constructors, one which takes all fields as args and another which takes no args. The second which takes no args is used when the application constructs an object outside of the database. Any relevant fields are set and then the doc is loaded, e.g.:
ExampleDoc exampleDoc = new ExampleDoc();
exampleDoc.setUniqueField("uniqueVal");
exampleDocRepository.save(exampleDoc);
The persistence constructor is used for the reverse - extracting a document from db and converting it to java object, e.g.
ExampleDoc exampleDoc = exampleDocRepository.findById(objectId)
Since the persistence constructor takes all arguments, I'd like to use lombok's @AllArgsConstructor annotation to avoid having to add this explicitly.
I tried using:
@ToString
@Document
@AllArgsConstructor
public class ExampleDoc {
@PersistenceConstructor
@Id
@Getter @Setter @NonNull private ObjectId id;
@Indexed(unique = true)
@Getter @Setter @NonNull private String uniqueField;
@Getter @Setter String field1
@Getter @Setter String field2
}
but this did not work. Is there a way to combine the 2 so I don't have to explicitly create a constructor that lists all fields?
Solution
According to https://projectlombok.org/features/constructor, to put annotations on the generated constructor, you can use onConstructor=@__({@AnnotationsHere})
So it should be
@AllArgsConstructor(onConstructor=@__({@PersistenceConstructor}))
public class ExampleDoc {
...
}
But do it at your own risk, as this feature is still experimental:
you can use onConstructor=@__({@AnnotationsHere}), but be careful; this is an experimental feature.
Answered By - yejianfengblue
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)