티스토리 뷰

Java/JPA

JPA, Composite Key, IdClass

hwangyoungjae 2021. 12. 3. 10:25
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

복합키를 IdClass로 구성하여 입력 및 가져오는 code를 정리

N + 1 문제는 fetchjoin과 distinct로 해결하고자 했으며, 추후에 QueryDSL로도 정리 예정

 

Entity

@Entity @Table(name = "member")
@Getter @Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Member {
    @EqualsAndHashCode.Include
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long id;

    private String name;

    @OneToMany(mappedBy = "member", fetch = FetchType.LAZY)
    private List<AssociationMember> associationMembers = new ArrayList<>();
}
@Entity @Table(name = "association")
@Getter @Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Association {
    @EqualsAndHashCode.Include
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "association_id")
    private Long id;

    private String name;

    @OneToMany(mappedBy = "association", fetch = FetchType.LAZY)
    private List<AssociationMember> associationMembers = new ArrayList<>();
}
@NoArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class AssociationMemberId implements Serializable {
    @EqualsAndHashCode.Include
    private Member member;
    @EqualsAndHashCode.Include
    private Association association;
}
@Entity @Table(name = "association_member")
@IdClass(AssociationMemberId.class)
@Getter @Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class AssociationMember {
    @EqualsAndHashCode.Include
    @Id @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member;

    @EqualsAndHashCode.Include
    @Id @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "association_id")
    private Association association;
}

DDL

create table `member`
(
    member_id bigint auto_increment primary key,
    name      varchar(255) null
);

create table `association`
(
    association_id bigint auto_increment primary key,
    name           varchar(255) null
);

create table `association_member`
(
    association_id bigint not null,
    member_id      bigint not null,
    primary key (association_id, member_id),
    constraint FKbhgfoulhcplvmuj5v3qg9k57q
        foreign key (association_id) references association (association_id),
    constraint FKe4bl75mb9i4m8ib5sw8otthay
        foreign key (member_id) references member (member_id)
);

Record setup

실행코드

public static void logic(EntityManager em) {
    for (int i = 1; i <= 3; i++) {
        Association association = new Association();
        association.setName("association" + i);
        em.persist(association);
    }

    Member member = new Member();
    member.setName("member");
    em.persist(member);

    for (int i = 1; i <= 3; i++) {
        AssociationMember am = new AssociationMember();
        am.setMember(member);
        am.setAssociation(em.find(Association.class, (long) i));
        em.persist(am);
    }
}

실행결과

Hibernate: insert into association (name) values (?)
Hibernate: insert into association (name) values (?)
Hibernate: insert into association (name) values (?)
Hibernate: insert into member (name) values (?)
Hibernate: select associatio0_.association_id as associat1_0_0_, associatio0_.name as name2_0_0_ from association associatio0_ where associatio0_.association_id=?
Hibernate: select associatio0_.association_id as associat1_0_0_, associatio0_.name as name2_0_0_ from association associatio0_ where associatio0_.association_id=?
Hibernate: select associatio0_.association_id as associat1_0_0_, associatio0_.name as name2_0_0_ from association associatio0_ where associatio0_.association_id=?
Hibernate: insert into association_member (association_id, member_id) values (?, ?)
Hibernate: insert into association_member (association_id, member_id) values (?, ?)
Hibernate: insert into association_member (association_id, member_id) values (?, ?)

값 가져오기

Member를 기준으로 Association 확인

실행

String jpql = "select distinct m from Member m join fetch m.associationMembers am join fetch am.association";
List<Member> members = em.createQuery(jpql, Member.class)
        .getResultList();
members.forEach(member -> {
    System.out.printf("> memberName: %s%n", member.getName());
    member.getAssociationMembers().forEach(am -> {
        System.out.printf(" > associationName: %s%n", am.getAssociation().getName());
    });
});

결과

Hibernate: select distinct member0_.member_id as member_i1_2_0_, associatio1_.association_id as associat1_1_1_, associatio1_.member_id as member_i2_1_1_, associatio2_.association_id as associat1_0_2_, member0_.name as name2_2_0_, associatio1_.member_id as member_i2_1_0__, associatio1_.association_id as associat1_1_0__, associatio2_.name as name2_0_2_ from member member0_ inner join association_member associatio1_ on member0_.member_id=associatio1_.member_id inner join association associatio2_ on associatio1_.association_id=associatio2_.association_id
Hibernate: select member0_.member_id as member_i1_2_0_, member0_.name as name2_2_0_ from member member0_ where member0_.member_id=?
> memberName: member
 > associationName: association1
 > associationName: association2
 > associationName: association3

 

 

AssociationMember를 기준으로 Member, Association 확인

실행

String jpql = "select am from AssociationMember am join fetch am.member m join fetch am.association a";
List<AssociationMember> resultList = em.createQuery(jpql, AssociationMember.class)
        .getResultList();
for (AssociationMember am : resultList) {
    System.out.printf("%s - %s%n", am.getMember().getName(), am.getAssociation().getName());
}

결과

Hibernate: select associatio0_.association_id as associat1_1_0_, associatio0_.member_id as member_i2_1_0_, member1_.member_id as member_i1_2_1_, associatio2_.association_id as associat1_0_2_, member1_.name as name2_2_1_, associatio2_.name as name2_0_2_ from association_member associatio0_ inner join member member1_ on associatio0_.member_id=member1_.member_id inner join association associatio2_ on associatio0_.association_id=associatio2_.association_id
member - association1
member - association2
member - association3

'Java > JPA' 카테고리의 다른 글

JPA, ManyToOne, FetchType, fetch join  (0) 2021.12.02
JPA, DynamicUpdate, DynamicInsert  (0) 2021.10.28
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함