개발/JPA

JPA 나만의 정리 (2) - lombok 어노테이션

멋진놈 2022. 7. 21. 11:14
728x90

@Builder

즉 클래스 레벨에서 @Builder 어노테이션을 붙이면 모든 요소를 받는 package-private 생성자가 자동으로 생성되며 이 생성자에 @Builder 어노테이션을 붙인 것과 동일하게 동작한다고 한다. 즉 클래스 레벨도 결국은 중간 단계를 거쳐 생성자 레벨로 변환되어 동작한다는 것이다.

@Builder
public class BuildMe {

    private String username;
    private int age;

}

위와 같은 BuildMe 클래스에 @Builder 어노테이션을 붙였을 때 생성된 클래스 파일을 IntelliJ의 도움을 받아 바이트 코드 분석해보면 다음과 같은 클래스로 변한 것을 볼 수 있다.

public class BuildMe {
    private String username;
    private int age;

    BuildMe(String username, int age) {
        this.username = username;
        this.age = age;
    }

    public static BuildMe.BuildMeBuilder builder() {
        return new BuildMe.BuildMeBuilder();
    }

    public static class BuildMeBuilder {
        private String username;
        private int age;

        BuildMeBuilder() {
        }

        public BuildMe.BuildMeBuilder username(String username) {
            this.username = username;
            return this;
        }

        public BuildMe.BuildMeBuilder age(int age) {
            this.age = age;
            return this;
        }

        public BuildMe build() {
            return new BuildMe(this.username, this.age);
        }

        public String toString() {
            return "BuildMe.BuildMeBuilder(username=" + this.username + ", age=" + this.age + ")";
        }
    }
}

 

@Getter

package com.example.dandy.history.dto.board;

import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
public class BuildMe {

    private String username;
    private int age;
}

@Getter를 추가 했을 시에

 

public String getUsername() {
    return this.username;
}

public int getAge() {
    return this.age;
}

추가가 됨.

 

@AllArgsConstructor

여기에 필드에 쓴 모든생성자만 만들어줌

이 애노테이션은 클래스에 존재하는 모든 필드에 대한 생성자를 자동으로 생성해줍니다.

 

만약 필드중에서 @NonNull 애노테이션이 마크되어 있다면 생성자 내에서 null-check 로직을 자동적으로 생성해줍니다.

 

allArgsConstructor이 있으면 필드 수에 상관없이 자동으로 넣어주지는 않고
UserDTO(id,name,email,age,mobile,profile_image,gender,birthyear,birthday){
this.id=id;
이런식으로 this.email, age 다 만들어주는거임
} 

 

롬복 코드

package com.example.dandy.history.dto.board;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
@AllArgsConstructor
public class BuildMe {

    private String username;
    private int age;
}

@AllArgsConstrcutor를 추가 했을 시

package com.example.dandy.history.dto.board;

public class BuildMe {
    private String username;
    private int age;

    public static BuildMeBuilder builder() {
        return new BuildMeBuilder();
    }

    public String getUsername() {
        return this.username;
    }

    public int getAge() {
        return this.age;
    }

    public BuildMe(final String username, final int age) {
        this.username = username;
        this.age = age;
    }

    public static class BuildMeBuilder {
        private String username;
        private int age;

        BuildMeBuilder() {
        }

        public BuildMeBuilder username(final String username) {
            this.username = username;
            return this;
        }

        public BuildMeBuilder age(final int age) {
            this.age = age;
            return this;
        }

        public BuildMe build() {
            return new BuildMe(this.username, this.age);
        }

        public String toString() {
            return "BuildMe.BuildMeBuilder(username=" + this.username + ", age=" + this.age + ")";
        }
    }
}

 

차이점은 

Buildme.BuildMeBuilder age(int age){
this.age = age;
return this;
}

이런 것들이

final로 됨. 

 

  public BuildMe(final String username, final int age) {
        this.username = username;
        this.age = age;
    }
        public BuildMeBuilder username(final String username) {
            this.username = username;
            return this;
        }

        public BuildMeBuilder age(final int age) {
            this.age = age;
            return this;
        }

이렇게 됨

 

Java에서 사용하는 final은 다음과 같습니다.

자바 언어에서 final은 오직 한 번만 할당할 수 있는 entity를 정의할 때 사용된다. final로 선언된 변수가 할당되면 항상 같은 값을 가진다. 만약 final 변수가 객체를 참조하고 있다면, 그 객체의 상태가 바뀌어도 final 변수는 매번 동일한 내용을 참조한다.

final은 다들 알고 있듯 궁극적인, 최후의 등을 뜻하는데요, Java에서도 비슷한 의미를 담고 있는 것 같네요.

final은 클래스, 메서드, 변수 각각에 붙을 수 있습니다. 구체적인 내용을 살펴볼게요.

 

@NoArgsConstructor

@NoArgsConstructor //기본 생성자를 만들어줌
package com.example.dandy.history.dto.board;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;



@NoArgsConstructor
public class BuildMe {

    private String username;
    private int age;
}

 

사용하면

 

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.dandy.history.dto.board;

public class BuildMe {
    private String username;
    private int age;

    public BuildMe() {
    }
}

 

@Entity

package com.example.dandy.history.dto.board;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;


@NoArgsConstructor
@Entity
public class BuildMe {
    @Id
    @Column(name = "id", nullable = false)
    private Long id;

    private String username;
    private int age;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

 

 

  컴파일 시에 

Hibernate: 
    
    create table build_me (
       id bigint not null,
        age integer not null,
        username varchar(255),
        primary key (id)
    ) engine=InnoDB

가 됨.

 

 

 

이 만들어짐.