danuri
오늘의 기록
danuri
전체 방문자
오늘
어제
  • 오늘의 기록 (307)
    • java (150)
      • java (33)
      • spring (63)
      • jpa (36)
      • querydsl (7)
      • intelliJ (9)
    • kotlin (8)
    • python (24)
      • python (10)
      • data analysis (13)
      • crawling (1)
    • ddd (2)
    • chatgpt (2)
    • algorithm (33)
      • theory (9)
      • problems (23)
    • http (8)
    • git (8)
    • database (5)
    • aws (12)
    • devops (10)
      • docker (6)
      • cicd (4)
    • book (44)
      • clean code (9)
      • 도메인 주도 개발 시작하기 (10)
      • 자바 최적화 (11)
      • 마이크로서비스 패턴 (0)
      • 스프링으로 시작하는 리액티브 프로그래밍 (14)
    • tistory (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

인기 글

태그

  • Security
  • POSTGIS
  • ChatGPT
  • 자바 최적화
  • Thymeleaf
  • Java
  • mockito
  • connection
  • docker
  • PostgreSQL
  • 마이크로서비스패턴
  • SWAGGER
  • 트랜잭션
  • Database
  • DDD
  • reactive
  • RDS
  • JPA
  • AWS
  • nuribank
  • Jackson
  • Spring
  • Saving Plans
  • 등가속도 운동
  • Bitmask
  • 도메인 주도 설계
  • Kotlin
  • gitlab
  • S3
  • CICD

최근 댓글

최근 글

hELLO · Designed By 정상우.
danuri

오늘의 기록

java/jpa

[Spring Data JPA] 예제 도메인 모델

2021. 5. 23. 18:30

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-JPA-%EC%8B%A4%EC%A0%84/

 

실전! 스프링 데이터 JPA - 인프런 | 강의

스프링 데이터 JPA는 기존의 한계를 넘어 마치 마법처럼, 리포지토리에 구현 클래스 없이 인터페이스 만으로 개발을 완료할 수 있습니다. 그리고 반복 개발해온 기본 CRUD 기능도 모두 제공합니다

www.inflearn.com

강의를 들으며 생각 정리 + "자바 ORM 표준 JPA 프로그래밍" 책 참고

 

예제 도메인 모델과 동작확인


앞으로 스프링 데이터 JPA 학습시 사용할 예제 도메인 모델을 설계하자.

도메인 모델은 단순하게 회원(Member) - 팀(Team) 엔티티가 다대일 양방향 연관관계를 맺도록 설계한다.

 

</entity/Member>

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;
    private String username;
    private int age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    public Member(String username) {
        this.username = username;
    }

    public Member(String username, int age, Team team) {
        this.username = username;
        this.age = age;
        if (team != null) {
            changeTeam(team);
        }
    }

    public void changeTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);
    }
}

 

</entity/Team>

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "name"})
public class Team {

    @Id
    @GeneratedValue
    @Column(name = "team_id")
    private Long id;
    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

    public Team(String name) {
        this.name = name;
    }
}

 

@NoArgsConstructor AccessLevel.PROTECTED : JPA 스펙상 기본 생성자를 열어두어야 한다. 외부에서 기본 생성자로 접근하는 것을 막기 위해 protected로 열어둔다.

 

@ToString : 가급적 내부 필드만 출력 (연관관계인 엔티티를 ToString에 포함하면 무한루프의 위험성이 있다)

 

Member -> changeTeam() : 양방향 연관관계 한번에 처리 (연관관계 편의 메서드)

+) Member가 Team을 바꾸면 기존 team.getMembers()에서는 Member를 삭제해야 하지 않나?

: Team은 연관관계의 주인이 아니므로 JPA 동작에 영향을 주지 않기 때문에 따로 삭제할 필요 없다. Member가 연관관계의 주인이고 DB에서 연관관계를 나타낼 때, Member 테이블의 외래키에만 의존한다.

확실하게 컬렉션에서 삭제를 해도 되지만 너무 복잡해지고, JPA와 DB 변경에 영향을 주지 않아서 이런 부분은 생략해도 된다.

 

간단하게 테스트 해본다.

@SpringBootTest
@Transactional
@Rollback(false)
class MemberTest {

    @PersistenceContext
    EntityManager em;

    @Test
    public void testEntity() {
        //given
        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");
        em.persist(teamA);
        em.persist(teamB);

        Member member1 = new Member("member1",10,teamA);
        Member member2 = new Member("member2",20,teamA);
        Member member3 = new Member("member3",30,teamB);
        Member member4 = new Member("member4",40,teamB);

        em.persist(member1);
        em.persist(member2);
        em.persist(member3);
        em.persist(member4);

        //초기화
        em.flush();
        em.clear();

        //when
        List<Member> members = em.createQuery("select m from Member m", Member.class)
                .getResultList();

        //then
        for (Member member : members) {
            System.out.println("member = " + member);
            System.out.println("-> member.team = " + member.getTeam());
        }
     }
}

-> DB 테이블 결과 확인, 지연 로딩 동작 확인

'java > jpa' 카테고리의 다른 글

[Spring Data JPA] 쿼리 메소드 기능  (0) 2021.05.24
[Spring Data JPA] 공통 인터페이스 기능  (0) 2021.05.23
[Spring Data JPA] 프로젝트 환경설정  (0) 2021.05.23
[JPA] 쿼리 파라미터 로그 남기기  (0) 2021.05.23
[JPA] API 개발 고급 - 실무 필수 최적화  (1) 2021.05.21
    'java/jpa' 카테고리의 다른 글
    • [Spring Data JPA] 쿼리 메소드 기능
    • [Spring Data JPA] 공통 인터페이스 기능
    • [Spring Data JPA] 프로젝트 환경설정
    • [JPA] 쿼리 파라미터 로그 남기기
    danuri
    danuri
    IT 관련 정보(컴퓨터 지식, 개발)를 꾸준히 기록하는 블로그입니다.

    티스토리툴바