0

Having these entity:

@Entity
@Data
@Builder
public class User {
    @Id
    private int id;
    private String name;
}

If i try to set the id:

@Bean
    CommandLineRunner dataLoader(UserRepository userRepo){
        return new CommandLineRunner() {
            @Override
            public void run(String... args) throws Exception {
                User u = User.builder()
                        .id(1)
                        .name("First User")
                        .build();
                userRepo.save(u);
            }
        };
    }

I got

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:794) ~[spring-boot-2.5.3.jar:2.5.3]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:775) ~[spring-boot-2.5.3.jar:2.5.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:345) ~[spring-boot-2.5.3.jar:2.5.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.3.jar:2.5.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.3.jar:2.5.3]
    at com.example.demo.DemoApplication.main(DemoApplication.java:16) ~[classes/:na]
Caused by: org.springframework.orm.jpa.JpaSystemException: No default constructor for entity:  : com.example.demo.domain.User; nested exception is org.hibernate.InstantiationException: No default constructor for entity:  : com.example.demo.domain.User
...

If i don't set the id, then no problem. So how do I can set the primary manually?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • Looks like you have the same issue as shown here `No default constructor for entity` https://stackoverflow.com/questions/34241718/lombok-builder-and-jpa-default-constructor – Pilpo Sep 02 '21 at 13:46

1 Answers1

2

In General: You sholdn't use @Data with Entities because the generated equals/hashCode and toString can lead to StackOverflowError if you have bi-directional entities.

Coming back to your question JPA needs a default constructor (no args constructor)

So I would recommend this:

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
    @Id
    private int id;
    private String name;
}
Simon Martinelli
  • 34,053
  • 5
  • 48
  • 82
  • 1) I don't understand your point of `StackoverfloError`, could you give an example please? 2) Why does not `@Builder` provide default (no-arg) constructor? Why does this behvaiour the `@Builder` overwrites? 3) Why does this issue (regarding the lack of default constructor) solves by adding `@AllArgsConstrutor`, which is *not* default constructor? – milanHrabos Sep 02 '21 at 14:00
  • 1) equals/hashCode/toString will follow the references and will produce an endless loop 2 and 3) Please read the API Doc https://projectlombok.org/api/lombok/Builder.html – Simon Martinelli Sep 02 '21 at 14:03
  • So when it is safe to use `@Data`, when in case of `@Entity`, it would create infinite loop? When it doesn't ? – milanHrabos Sep 02 '21 at 14:06
  • Btw, your annotations are not enough. It will fail anyway, unless `@AllArgsConstrutor` is provided. The error otherwise: `constructor User in class com.example.demo.model.User cannot be applied to given types; required: no arguments found: int,java.lang.String reason: actual and formal argument lists differ in length` – milanHrabos Sep 02 '21 at 14:11
  • Ah you're right the Builder requires the AllArgsConstructor. – Simon Martinelli Sep 02 '21 at 14:13
  • When you are absolutely sure that your classes don't have bi-directional or circular references then it's safe to use @Data – Simon Martinelli Sep 02 '21 at 14:14
  • Where is the bi-directional reference in my case? I have no object in User class that has User back reference declared. I see no bi-directional relationship your are talking about – milanHrabos Sep 02 '21 at 14:31
  • I didn't say you have this. I just said that @Data should be used with caution in combination with JPA – Simon Martinelli Sep 02 '21 at 14:35
  • Still don't understand, how bi-directional reference could cause infinite loop. I thought the `Equals()` and `toString()` are related to one class only, even id there is reference to another (which could have back reference). Still these function are only related to a particular function, so how could there arise some bi-directional reference? – milanHrabos Sep 02 '21 at 18:37
  • the methods will use EVERY field of the class and if that is another entity it will call the method on that field as well https://stackoverflow.com/questions/54653734/lombok-java-lang-stackoverflowerror-null-on-tostring-method/54654008 – Simon Martinelli Sep 03 '21 at 06:08