I want to use a data class in Lombok. Since it has about a dozen fields, I annotated it with #Data in order to generate all the setters and getter. However there is one special field for which I don't want to the accessors to be implemented.
How does Lombok omit this field?
You can pass an access level to the #Getter and #Setter annotations. This is useful to make getters or setters protected or private. It can also be used to override the default.
With #Data, you have public access to the accessors by default. You can now use the special access level NONE to completely omit the accessor, like this:
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private int mySecret;
According to #Data description you can use:
All generated getters and setters will be public. To override the
access level, annotate the field or class with an explicit #Setter
and/or #Getter annotation. You can also use this annotation (by
combining it with AccessLevel.NONE) to suppress generating a getter
and/or setter altogether.
Related
Using Jackson with Lombok's #Accessors(fluent=true) requires to add #JsonAutoDetect(Visibility.Any) annotation:
#Data
#NoArgsConstructor
#Accessors(fluent=true)
public class Pojo{
private String fieldOne;
private String fieldTwo;
}
I am curious of the performance of Visibilty.Any. Does it use reflection or compile time hooks are added?
Jackson uses reflection plus caching to implement serialisation and deserialisation processes anyway. Using this annotation does not add any noticeable performance cost. For more info, take a look how it is implemented: JsonAutoDetect.java. It allows you to change default visibility configuration for fields, getters, setters, creators and constructors.
#Data
public abstract class B {
private final String str;
}
#Data
public class A extends B{
private final String s;
}
Data on class A complains in intellij, but the codes can get compiled successfully through command line, not sure what to do
One problem is that #Data is meant for mutable data and there's nothing mutable in your classes. So using #Data is simply wrong... and whether it compiles or not doesn't really matter.
If you want mutable data, then remove the final field. For immutable data, make all fields final and use #Value. Sometimes, partially mutable data is needed, but I try hard to avoid it as it's confusing (some fields can be set, some can't) and they provide disadvantages of both.
The other problem is that Lombok can't access class hierarchies. With B having a final field, you need it to be initialized in the constructor, which means that A's constructor has to call a non-default constructor. This isn't possible with Lombok. There's #Superbuilder in Lombok, which is about the only feature of Lombok dealing well with class hierarchies.
The #Data annotation does not add a default contructor.
Try to add a #NoArgsConstructor to your Base Class B to generate a default constructor with Lombok.
You can also read up what #Data actually means here.
This does not event compile. In Intellij, when you are not sure what is the problem with lombok code, you can open class in which you are unsure, go on Refactor -> Delombok -> All lombok annotations and you will see what lombok actually create for you.
Is there a way to customise the generated code for #Setter?
Consider the following simple class:
#Entity
#Getter
#Setter
#NoArgsConstructor
public class MyEntity implements Serializable {
#Id private long id;
#OneToMany
private Set<AttributeColumn> columns = new HashSet<>();
public void setColumns(Set<AttributeColumn> columns) {
this.columns.clear();
this.columns.addAll(columns);
}
}
I want Lombok to generate the Setter for columns as I implemented it in the example above. This should only be done on classes annotated with #Entity and on attributes that are a Collection. The Setter for other attributes, in this example id should be generated as usual.
Is there a way to customise the generation of the Setter code depending on those criteria?
No.
No, there's no such feature and no plans for it.
As already stated in a comment, you could do it yourself, but it's not easy at all. Moreover, you'd have to decide to either hardcode the logic (simple but probable unusable for others) or interpret something like
#SetterWhen(#Or(
#Condition(annotatedWith=Entity.class),
#Condition(declaredType=Collection.class)))
which is close to impossible to implement (as this information is unavailable when Lombok runs).
Currently, all you can do is to allow on suppress the generation on a per field basis. There's no possibility to generate a different setter, however
there's a related feature: #Singular, which may or may not help you.
After scouring the Lombok feature-list and in particular the documentation for the Getter/Setter and #Value annotations I have not been able to find any setting that suppresses the code generated by #Getter.
In practice, #Value is shorthand for: final #ToString #EqualsAndHashCode #AllArgsConstructor #FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) #Getter
This is important as I do not want to leak references to objects that are themselves mutable.
Effective Java references this type of issue in "Item 39: Make defensive copies when needed". It seems that #Wither could partly solve this issue by making actual defensive copies but I want to avoid leaking attributes what so ever, regardless of them being mutable.
While it is possible to roll one's own #Value annotation that omits the #Getter I would, of course, prefer not to as that would add unwarranted complexity to the codebase if such a setting already exists.
You could use:
#Value
#Getter(AccessLevel.NONE)
AccessLevel.NONE instructs Lombok to not generate the getters. That's the best you can do right now.
I am using hibernate for entity persistance in application along with spring mvc I have a multiple #Transient fields in an entity in a application is there a way to tell Json parser to automatically ignore all #Transient annotated fields in entity without the need to use #JsonIgnore or #JsonIgnoreProperties
#Transient is to indicate the field is not persistent. #JsonIgnore is to indicate the field is to be ignored by the serialization/deserialization processor, they have very different meanings.
One option is have Json processor base serial/deserialization from available fields (vs getter/setters), then mark your #Transient fields with additional transient keyword. If you have getters/setters, you'll also need to add appropriate visibility rules. For example, this will serialize all fields not marked with transient.
#JsonAutoDetect(fieldVisibility=Visibility.ANY, getterVisibility=Visibility.NONE, setterVisibility = Visibility.NONE)
I have found a better way instead of using #jsonignore to the fields in an entity
on child class use JsonBackreference and on parent use JsonManagedReference
For more information go through this blog post