Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

코틀린의 Data Class를 자바에서도 지원하는가? #1

Open
jymaeng95 opened this issue Jan 17, 2023 · 1 comment
Open

코틀린의 Data Class를 자바에서도 지원하는가? #1

jymaeng95 opened this issue Jan 17, 2023 · 1 comment
Assignees
Labels
TMI More Information

Comments

@jymaeng95
Copy link

jymaeng95 commented Jan 17, 2023

코틀린의 Data Class를 자바에서도 지원하는가?

  • 기존 Java 코드에서는 이러한 Data class를 만들기 위해선 hashCode, toString, equals 등을 변경없이 사용하는
    보일러 플레이트 코드로 만듦
public class Person {
	private final String name;
	private final int age;

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
		
	@Override 
	public int hashCode() { ... }
		
	@Override
	public boolean equals(Object obj) { ... }
		
	@Override
	public String toString() { ... }
	
	... getter, setter ...
}
  • Java 14부터 Kotlin의 Data Class와 유사한 record 키워드를 지원하기 시작
public record Person (String name, int age) {  }
  • 자동으로 필드를 갖는 constructor, getter, equals, hashCode, toString 지원
  • 필요한 메서드 추가 및 오버라이딩(재정의) 가능

record 키워드로 정의된 getter는 getXXX()가 아닌 XXX로 접근

person.getName() // X
person.name() // O

참고 링크
https://www.baeldung.com/java-record-keyword

@jymaeng95 jymaeng95 added the TMI More Information label Jan 17, 2023
@jymaeng95 jymaeng95 self-assigned this Jan 17, 2023
@milkcoke
Copy link
Member

milkcoke commented Jan 19, 2023

JPA Embeddable 타입에서 record 를 활용할 수 있는가?

🚫 불가능

실험 예제

Member.java

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Member extends BaseEntity {
// .. 중략
    @Embedded
    private Address address;
// .. 중략
}

@embeddable, @Embedded 로 사용되는 임베디드 타입은
다음과 같이 쓰는 것이 관례.

  • 불변객체로 생성해야함
  • 임베디드 값타입 비교를 위해 equals(), hashCode() 오버라이딩

Address.java

@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Address {
    private String country;
    private String city;
    private String street;
    private String zipCode;

    public Address(String country, String city, String street, String zipCode) {
        this.country = country;
        this.city = city;
        this.street = street;
        this.zipCode = zipCode;
    }

    // .... ㅡㅡ;
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Address address = (Address) o;
        return Objects.equals(country, address.country) && Objects.equals(city, address.city) && Objects.equals(street, address.street) && Objects.equals(zipCode, address.zipCode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(country, city, street, zipCode);
    }

}

record 키워드를 사용하면 equals(), hashCode() 오버라이딩 없이 값 비교가 가능하지 않을까?

다음과 같은 boilerPlate 코드를 없애고싶다.

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Address address = (Address) o;
        return Objects.equals(country, address.country) && Objects.equals(city, address.city) && Objects.equals(street, address.street) && Objects.equals(zipCode, address.zipCode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(country, city, street, zipCode);
    }

record 키워드 적용 실패

public record Address(String country, String city, String street, String zipCode) {

   //⚠️ Non-canonical record constructor must delegate to another constructor
    public Address() {

    }
}

기본 생성자를 record 키워드에 적용할 수 없다.

원인

  1. JPA의 Entity class 는 모두 protected 또는 public 의 기본 생성자를 가져야만함.
  2. 별도의 생성자 정의 시도시 Non-canonical record constructor must delegate to another constructor 에러 발생
    => record 타입에 JPA 가 요구하는 파라미터가 없는 기본 생성자 정의 불가능
    => JPA 가 정상적으로 인식할 수 없음.

결론

JPA Entity 에는 값 비교가 필요하면 그냥 boilerplate 코드를 쓰자.
record 키워드를 JPA Entity 에 사용하는 것은 적절하지 않다.

참고

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
TMI More Information
Projects
None yet
Development

No branches or pull requests

2 participants