inblog logo
|
p4rksk
    JavaSpringFrameWork

    52. LazyLoding을 사용한게시글 상세보기

    박선규's avatar
    박선규
    Mar 18, 2024
    52. LazyLoding을 사용한게시글 상세보기
    Contents
    빌드업 패턴게시글 상세보기
    인증 orm
    User 객채만들기
    notion image
    이렇게 안되는 이유
    암호화를 할 경우 (해쉬 )그럼 12자가 가볍게 넘기 때문이다.
    그래서 저 어노에티션은 안붙이는게 좋다
     
     
    연관 관계를 맺어야 수정을 한번만 할 수 있다
     
     

    @ManyToOne

    💡
    @ManyToOne 어노테이션은 다대일(N:1) 관계를 나타내며, 이 경우에는 여러 개의 엔티티가 하나의 엔티티에 매핑됩니다.
    여기서 User 엔티티가 @ManyToOne 관계로 user 필드로 매핑됩니다. user 필드는 User 엔티티의 객체를 참조합니다.
    그리고 user 필드에 대한 매핑은 user_id 컬럼으로 이루어집니다. 컬럼명은 변수명_ 으로 자동으로 설정됩니다.

    빌드업 패턴

    💡
    빌더는 복잡한 객체들을 단계별로 생성할 수 있도록 하는 생성 디자인 패턴입니다.
    자기 자신을 return한다(자기자신 = 객체)
    public class User { private Integer id; private String username; private String password; private String email; @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + email + '\'' + '}'; } public static User builder(){ return new User(); } public User id(int id){ this.id=id; return this; } public User username(String username){ this.username=username; return this; } public User password(String password){ this.password=password; return this; } public User email(String email){ this.email=email; return this; } public static void main(String[] args){ User user = User.builder().id(1).username("ssar"); User user2 = User.builder().id(2).username("cos").password("1234"); User user3 = User.builder().username("love").password("1234").id(3); System.out.println(user); System.out.println(user2); System.out.println(user3); } }
    notion image

    장점

    생성자를 안만들어도 된다.(생성자를 만들면 생성자에 들어갈 수 있고 없는게 있는데 그럼 그때마다 생성자를 만들어야된다.)
    순서에 상관없다
     
    사용하는 이유는 =추후에 값을 바꾸기 위해 쓰는 패턴이 아니라 초기에 값을 설정할 때 쓰기 위한 패턴
     
    integer사용해야하는 이유는

    게시글 상세보기

    📎
    학습목표
    1. Eager (연관된 객체에 값을 채워준다)
    1. Lazy (연관된 객체에 값을 채워주지 않는다)
    1. Lazy Loading
    1. Object Relation Mapping
    1. 직접 조인

    EAGER

    💡
    조인만하는게 아니라 단어뜻 그대로 열정적으로 채워준다 보니 만약 보드를 조회하는 쿼리를짜서 던지면 USER를 조회하는 쿼리도 발동 돼 총 두 번 된다.
    package shop.mtcoding.blog.user; import jakarta.persistence.*; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.CreationTimestamp; import java.sql.Timestamp; @NoArgsConstructor @Data @Table(name = "user_tb") @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(unique = true) private String username; private String password; private String email; @CreationTimestamp//ps를 -> db로 갈때 날짜로 주입 됨 private Timestamp createdAt; @Builder public User(Integer id, String username, String password, String email, Timestamp createdAt) { this.id = id; this.username = username; this.password = password; this.email = email; this.createdAt = createdAt; } }
    notion image
     
     
     
     
    public Board findById(int id){ //id, title, content, user_id(이질감), created_at; Board board = em.find(Board.class, id); return board; }
    💡
    Board를 조회하면user_id를 User 객체의 필드 id에 담아서 board 객체를 만들어준다.
     
     
    notion image
     
     
     
     

    조인을 안하는 lAZY

    package shop.mtcoding.blog.board; import jakarta.persistence.*; import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.CreationTimestamp; import shop.mtcoding.blog.user.User; import shop.mtcoding.blog.util.MyDateUtil; import java.sql.Timestamp; @NoArgsConstructor @Data @Table(name = "board_tb") @Entity public class Board { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String title; private String content; // @JoinColumn(name = "user_id") @ManyToOne(fetch = FetchType.LAZY)//연관 관계로 본다 private User user; //user_id 변수명(객체)_객체 필드 명(칼럼) @CreationTimestamp//ps를 -> db로 갈때 날짜로 주입 됨 private Timestamp createdAt; public String getTime(){ return MyDateUtil.timestampFormat(createdAt); } }
    notion image
    @Test public void findById(){ //given int id =1; //when boardRepository.findById(id); }
    notion image
    public Board findByIdJoinUser(int id){ Query query = em.createQuery("select b from Board b join fetch b.user u where b.id = :id", Board.class); query.setParameter("id", id); return (Board) query.getSingleResult(); }
     

    EAGER 대신 LAZY를 사용하는 이유

    💡
    LAZY로 설정하고
    조인이 필요 할 때 직접 JOINQUERY를 짠다.
    왜냐하면 EAGER로 할경우에 디폴트가 JOIN으로 되기때문에 화면에 불 필요한곳 (게시글 목록보기에 USER객체의 해당하는 필드가 필요없다)JOIN을 하기때문이다.
     

    LAZY loding

    📎
    LAZY상태에서 연관된 객체의 PK아닌 필드 값을 접근을 하면 지연 로딩이 된다. 이거 사용하지 말고 JOIN을 하는게 더 좋음
    @Test public void findById_test() { int id = 1; System.out.println("start - 1"); Board board = boardRepository.findById(id); System.out.println("start - 2"); System.out.println(board.getUser().getId()); System.out.println("start - 3"); System.out.println(board.getUser().getUsername());/ }
    notion image
    .getUser().getUsername()은 null 값이기 때문에 lazy loding이 일어난다.
     

    orm

    📎
     
     

    우리가 선택 해야 되는 전략.

    • 결론:lazy전략을 사용하고 필요한 경우 직접 조인하자.
     
     

    프로젝트 적용

    📎
    join할 때 는 fetch해서 select 절을 프로젝션 해줘야 된다.
    이렇게 하는 이유는 DTO를 사용 안하려고 빌드업 패턴 사용
    notion image
    Share article
    Contents
    빌드업 패턴게시글 상세보기

    p4rksk

    RSS·Powered by Inblog