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

박선규's avatar
Mar 18, 2024
52. LazyLoding을 사용한게시글 상세보기
인증 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

p4rksk