Error 해결

[Entity 생성자 Error]

sintory-04 2025. 1. 11. 17:07

1. 상황

연습 문제를 푸는 과정 중 Repository 에서 saved가 되지 않는 상황이 생겼다.

이렇게 이메일과 비밀번호를 넣으면 Controller에서

@PostMapping("/join")
  public String createMember(MemberForm form){
    System.out.println(form.toString());
    // 1. DTO를 엔티티로 변환
    Member member = form.toEntity();
    System.out.println(member.toString());
    // 2. 레퍼지토리로 Entity를 DB에 저장
    Member saved = memberRepository.save(member);
    System.out.println(saved.toString());
    return "";
  }

레퍼지토리에 Entity를 DB에 저장하여야하는데. 이게 되지 않는 것이다.

실행 로그는 아래와 같았다.

MemberForm{email='asdf@ansdf.com', password='asdf'}
Member{email='asdf@ansdf.com', password='asdf'}
2025-01-11T16:54:19.757+09:00 ERROR 21168 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.orm.jpa.JpaSystemException: No default constructor for entity : com.example.firstproject.entity.Member] with root cause

org.hibernate.InstantiationException: No default constructor for entity : com.example.firstproject.entity.Member
...

 

2. 원인 분석

위의 오류 코드에서 중요한 부분은 No default constructor for entity 라고 되어 있는 부분이다. 

엔티티에 대한 기본 생성자가 없다는 것이다.

Entity의 @ID 생성시 @GeneratedValue 를 사용하였기 때문에 기본생성자를 생략했어도 큰 문제는 없었으나,

원래 JPA는 기본 생성자를 요구한다. JPA가 객체를 DB와 동기화하거나 조회할 때, 리플렉션을 통해 객체를 생성하기 때문이다.

- JPA는 Entity를 DB와 동기화하거나 영속성 컨텍스트에 관리하기 위해 객체 생성 및 초기화 작업을 수행한다.

- 이때 기본 생성자를 사용해 객체를 생성한 후 DB 값을 채운다. > 기본생성자가 없으면 이러한 과정을 실패하게된다.

결론은 기본 생성자를 넣어주면, 이러한 문제를 해결한다는 것!

 

3. 해결 방법

Entity.java파일에 기본 생성자를 작성해준다.

@Entity
public class Member {
  // 기본 생성자
  public Member() {
  }
  
  @Id
  private String email;
  @Column
  private String password;

  public Member(String email, String password) {
    this.email = email;
    this.password = password;
  }

  @Override
  public String toString() {
    return "Member{" +
            "email='" + email + '\'' +
            ", password='" + password + '\'' +
            '}';
  }
}

그러면 3가지 코드가 정상적으로 출력하는 걸 볼 수 있다.

MemberForm{email='asdf@ansdf.com', password='asdf'}
Member{email='asdf@ansdf.com', password='asdf'}
Member{email='asdf@ansdf.com', password='asdf'}