17

I am using the following:

@Entity
@Data
@Builder
@NoArgsConstructor(force = true)
public class User {
    private String id;
    private String firstName;
    private String lastName;
}

what I want to achieve: for JPA usage, I need a POJO with noArgConstructor, getters/setters and equals/hashCode/toString.

For instance creation (for example in tests) I want to use User.builder().build();

Problem: it does not compile, there seems to be an issue with the NoArgConstructor vs. RequiredFieldsConstructor:

Error:(15, 1) java: constructor User in class x.y.z.User cannot be applied to given types;
required: no arguments
found:    java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String
reason: actual and formal argument lists differ in length

Update: The error occurs when I try to create a new entity via new ... the builder() works.

What do I miss? Isn't it possible to use @Data, @Entity and @Builder at the same time?

cellepo
  • 4,001
  • 2
  • 38
  • 57
Jan Galinski
  • 11,768
  • 8
  • 54
  • 77

4 Answers4

18

try this code with lombok version 1.16.18 over :

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class User {
    private String id;
    private String firstName;
    private String lastName;
}
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
장재훈
  • 621
  • 1
  • 6
  • 9
  • 6
    This is correct example, but generaly you can not use @Data on any @Entity! Equals, hashCode and toString can go to conflict with JPA spec or with "lazy load". – Lubo Oct 22 '19 at 13:20
  • Yes, I agree with you. So it's better to add "@Getter", "@Setter", instead of "@Data". – 장재훈 Aug 10 '20 at 11:59
  • @Lubo if we use Data annotation on entity classes, you mean to say it doesn't take care of the field which we mentioned as primary key field, in generating equals and hashcode ? what do you mean by conflict with JPA spec ? can you explain more. – Hiro_Hamada Aug 01 '23 at 12:23
  • @Hiro_Hamada Hi, I have explained it a bit more in my answer. Have a look at https://stackoverflow.com/a/58505239/11152683 please. Absolute detailed article is linked there. – Lubo Aug 08 '23 at 04:01
9

Beware of that data objects aren't entities! Simply put, there is problem with hashcode/equals (when it considers id fields) and also toString method with lazy loaded parts of entity. For reference you can check Vlad Mihalceas article.

You should:

  • exclude id fields from hashcode/equals
  • exclude association fields which are not managed in given entity from hashcode/equals
  • exclude all lazy loaded fields from toString method
  • exclude fields possibly causing circular references from toString method

For sure read at least something on topic of how does JPA do "dirty checking" before beeing confident that your handwritten or generated equals/hashcode method is ok.

Lubo
  • 1,621
  • 14
  • 33
4

I will answer my own question by summerizing the comments.

First of all, thanks to @RoelSpilker, you can use Builder and Data together on one Pojo if you explicitly provide AllArgs- and NoArgs- constructors:

 @RequiredArgsConstructor
 @NoArgsConstructor
 @Data
 @Builder
 public class Person {...}

But: the builder created for this class will not know any inherited fields. For my use case (having some AbstractEntities) this renders the solution useless and I will stick with manual helpers/builders for now.

Jan Galinski
  • 11,768
  • 8
  • 54
  • 77
  • 7
    Your answer does not mention the class is a JPA entity, but question says explicitly about entity. If that's the case, you should not use `@Data` and `@Entity` together. Lombok will generate `hashCode()` and `equals()` for you using all fields - `id` included, which should be avoided. Or at least treated with care. – wst Mar 14 '17 at 13:34
  • 1
    Lombok is updated now, try `@SuperBuilder` annotation on both parent and child class – vikingsteve Feb 07 '19 at 08:34
  • @vikingsteve, So if there is a nested structure of classes, like Employee has a Address, Address has Street, City, State, Country, Zipcode. So here, do you mean to say, you'll have to add `@SuperBuilder` in each & every class? – Aniket Oct 28 '21 at 21:40
0

In the Lombok documentation it is written: Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();

Do you use this syntax for your purpose? According to your description it's not the case, and could explain the error you get?

Xendar
  • 466
  • 1
  • 6
  • 15
  • I do not get the error when I use the builder, I get the error when I use the default constructor (which I have to do since it is an entity). Will update the question. – Jan Galinski Nov 09 '16 at 21:37