๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

SpringBoot

[SpringBoot] ๐Ÿ’ฅ ๊ด€์Šต์ ์ธ EntityManager ์˜ clear ์‚ฌ์šฉ์„ ๋ฉˆ์ถ”์„ธ์š” (feat. JPQL ๊ณผ 1์ฐจ ์บ์‹œ)

๐Ÿค” ๊ถ๊ธˆ์ฆ์„ ๊ฐ–๊ฒŒ ๋œ ๊ณ„๊ธฐ

 

๋ฆฌ๋ทฐ์–ด ๋ถ„๊ณผ ๋Œ€ํ™”๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋‹ค๊ฐ€, EntityManager ์˜ clear ๋ฅผ ์‚ฌ์šฉํ•œ ์ด์œ ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์„ ๋ฐ›์•˜๋‹ค. ์ด์— ๋Œ€ํ•ด ๋‚˜๋Š” ๋‹จ์ˆœ ์ง€์‹ ํ™•์ธ ์ธก๋ฉด์ด๊ฒ ๊ฑฐ๋‹ˆ - ํ•˜๊ณ  ๋”ฑํžˆ ๋‚˜์˜ ์ง€์‹์„ ๋”๋ธ” ์ฒดํฌํ•˜์ง€ ์•Š๊ณ  ๋‹ต๋ณ€์„ ์ž‘์„ฑํ–ˆ์—ˆ๋‹ค.

 

๋‚˜์˜ ์˜๋„๋Š” ๋ ˆํฌ์ง€ํ† ๋ฆฌ์˜ ์ฝ”๋“œ๊ฐ€ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๊ฒ€์ฆ์„ ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.

๋งŒ์•ฝ EntityManager ์˜ clear ๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ฉด ์‹ค์ œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ 1์ฐจ ์บ์‹œ๋ฅผ ํ™•์ธํ•ด ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ž‘์„ฑํ•œ ๋Œ€๋ถ€๋ถ„์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ์Šต๊ด€์ ์œผ๋กœ EntityManager.clear ๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค.

 

๋‚˜๋ฆ„ ํ™•์‹ ์ด ์žˆ์—ˆ๊ธฐ์— ํ˜ธ๊ธฐ๋กญ๊ฒŒ ๋Œ€๋‹ตํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋ฆฌ๋ทฐ์–ด์˜ ๋‹ต๋ณ€์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•˜๋‹ค.

 

 

 

์˜ค์‹นํ•œ ๊ธฐ๋ถ„์ด ๋“ค์—ˆ๋‹ค. ํ˜น์‹œ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์•ˆ ํƒ€๋‚˜..?

 

 

๐Ÿ”Ž ์ด ๊ธ€์„ ์ด๋Ÿฐ ๋ถ„๋“ค๊ป˜ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค

  • ์œ„์˜ ๋ฆฌ๋ทฐ ๋‚ด์šฉ์—์„œ ๋‚˜์™€ ๊ฐ™์ด ์˜ค์‹นํ•˜์‹  ๋ถ„๋“ค
  • ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ž˜ ๋ชจ๋ฅด์‹œ๋Š” ๋ถ„๋“ค
  • ์Šต๊ด€์ ์œผ๋กœ EntityManager ์˜ clear ๋ฅผ ํ•˜๊ธฐ๋Š” ํ–ˆ๋Š”๋ฐ ์†”์งํžˆ ์™œ ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋Š” ๋ถ„๋“ค

 

์ด์ œ๋ถ€ํ„ฐ ์—ฌ๋Ÿฌ ์‹คํ—˜๋“ค์„ ํ•ด๋ณด์ž. ์ง„์งœ๋กœ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํƒ€๋Š”์ง€ ์•ˆํƒ€๋Š”์ง€!

 

์šฐ์„ , ๊ธฐ๋ณธ์ ์ธ ์„ธํŒ…์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

@Entity
@Getter
@NoArgsConstructor
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne
    private Team team;

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

@Entity
@NoArgsConstructor
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

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

 

๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜์ž๋ฉด ํšŒ์›์ด ํŒ€์— ์†ํ•ด์žˆ๋Š”, Member ๊ฐ€ Team ์„ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ตฌ์กฐ๋‹ค.

 

public interface MemberJpaRepository extends JpaRepository<Member, Long> {
    List<Member> findByTeam(Team team);
}

 

๊ทธ๋ฆฌ๊ณ  MemberJpaRepository ์—๋Š” Team ์„ ํ†ตํ•ด Member ๋“ค์„ ์ฐพ์•„์˜ค๋Š” findByTeam ์ด๋ผ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

 

๋‹ค์‹œ ํ•œ๋ฒˆ ์งš์–ด๋ณด์ž. ๋‚˜์˜ ๊ฐ€์„ค์€

ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ๋•Œ EntityManager#clear ๋ฅผ ํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” 1์ฐจ ์บ์‹œ๋ฅผ ํƒ€์ง€ ์•Š๊ณ  ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๋„๋ก ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.

โœ… 1. ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด EntityManager#clear ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ

@Test
@DisplayName("ํŒ€์— ์†ํ•˜๋Š” ๋ฉค๋ฒ„๋“ค์„ ์กฐํšŒํ•œ๋‹ค")
void test1() {
    // given
    Team team = new Team("ํžˆ๋กœ์˜ ํŒ€");
    entityManager.persist(team);

    Member ํžˆ๋กœ1 = new Member("ํžˆ๋กœ1", team);
    entityManager.persist(ํžˆ๋กœ1);

    Member ํžˆ๋กœ2 = new Member("ํžˆ๋กœ2", team);
    entityManager.persist(ํžˆ๋กœ2);

    Member ํžˆ๋กœ3 = new Member("ํžˆ๋กœ3", team);
    entityManager.persist(ํžˆ๋กœ3);

    Member ํžˆ๋กœ4 = new Member("ํžˆ๋กœ4", team);
    entityManager.persist(ํžˆ๋กœ4);

    entityManager.flush();
    entityManager.clear();

    // then
    System.out.println("======");
    memberJpaRepository.findByTeam(team).forEach(member -> System.out.println(member.getName()));
}

 

์œ„์™€ ๊ฐ™์ด Team ํ•˜๋‚˜๋ฅผ ์ €์žฅํ•˜๊ณ , ์ด์— ํ•ด๋‹นํ•˜๋Š” Member ๋“ค 4๊ฐœ๋ฅผ ์ €์žฅํ–ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ €์žฅ๋œ Team ์„ ๊ธฐ์ค€์œผ๋กœ Member ๋“ค์„ ์กฐํšŒํ•ด์˜ค๋„๋ก ํ–ˆ๋‹ค.

======
Hibernate: 
    select
        m1_0.id,
        m1_0.name,
        m1_0.team_id 
    from
        member m1_0 
    where
        m1_0.team_id=?
Hibernate: 
    select
        t1_0.id,
        t1_0.name 
    from
        team t1_0 
    where
        t1_0.id=?
ํžˆ๋กœ1
ํžˆ๋กœ2
ํžˆ๋กœ3
ํžˆ๋กœ4

 

๊ทธ๋ ‡๊ฒŒ ํ–ˆ๋”๋‹ˆ, ์œ„์™€ ๊ฐ™์ด ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ”๋‹ค. ์—ฌ๊ธฐ๊นŒ์ง€๋Š” clear ๋ฅผ ํ•˜๋ฉด, ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ„๋‹ค ๋ผ๋Š” ๋‚ด ๊ฐ€์„ค์— ๋ถ€ํ•ฉํ•œ๋‹ค.

 

โœ… 2. ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด EntityManager#clear ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ

======
Hibernate: 
    select
        m1_0.id,
        m1_0.name,
        m1_0.team_id 
    from
        member m1_0 
    where
        m1_0.team_id=?
ํžˆ๋กœ1
ํžˆ๋กœ2
ํžˆ๋กœ3
ํžˆ๋กœ4

 

clear ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•˜์Œ์—๋„ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ”๋‹ค. ์ฆ‰, 1์ฐจ ์บ์‹œ์— ์ด๋ฏธ ์กฐํšŒํ•ด์•ผ ํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋ชจ๋‘ ์กด์žฌํ•จ์—๋„ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ„ ๊ฒƒ์ด๋‹ค.

clear ๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ฉด ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€์ง€ ์•Š๊ณ  1์ฐจ ์บ์‹œ๋งŒ์„ ์ฐธ์กฐํ•œ๋‹ค๋Š” ๋‚ด ๊ฐ€์„ค์ด ํ‹€๋ฆฐ ์ƒํ™ฉ์ด๋‹ค.


 

์—ฌ๊ธฐ๊นŒ์ง€ ๋ดค์„ ๋•Œ ์šฐ๋ฆฌ๋Š” ์–ด๋ ดํ’‹์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๋ก ์„ ๋‚ด๋ฆด ๊ฒƒ์ด๋‹ค.

์•„! EntityManager#clear ์•„๋ฌด ์˜๋ฏธ ์—†๋„ค. ๊ทธ๋ƒฅ ๋‹ค ์ฟผ๋ฆฌ ๋‚˜๊ฐ€๋„ค! ์‹ถ์–ด์ง„๋‹ค.

โœ… 3. findById ์— ๋Œ€ํ•ด EntityManager#clear ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ

๊ทธ๋ ‡๋‹ค๋ฉด ๋‚˜์˜ ๊ฐ€์„ค์ด ํ‹€๋ ธ์Œ์„ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•ด ๋˜ ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด์ž.

์ด๋ฒˆ์—๋Š” ์ง์ ‘ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š๊ณ  findById ๋ฅผ ํ†ตํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณผ ๊ฒƒ์ด๋‹ค.

 

@Test
@DisplayName("id ๋ฅผ ํ†ตํ•ด ๋ฉค๋ฒ„๋ฅผ ์กฐํšŒํ•œ๋‹ค")
void test2() {
    // given
    Team team = new Team("ํžˆ๋กœ์˜ ํŒ€");
    entityManager.persist(team);

    Member ํžˆ๋กœ1 = new Member("ํžˆ๋กœ1", team);
    entityManager.persist(ํžˆ๋กœ1);

    Long id = ํžˆ๋กœ1.getId();

    entityManager.flush();
    entityManager.clear();

    // then
    System.out.println("======");
    memberJpaRepository.findById(id);
}
======
Hibernate: 
    select
        m1_0.id,
        m1_0.name,
        t1_0.id,
        t1_0.name 
    from
        member m1_0 
    left join
        team t1_0 
            on t1_0.id=m1_0.team_id 
    where
        m1_0.id=?
ํžˆ๋กœ1

 

์—ฌ์ „ํžˆ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๊ธฐ๊นŒ์ง€๋Š” ์•„๊นŒ์™€ ๋˜‘๊ฐ™๋‹ค.

 

โœ… 4. findById ์— ๋Œ€ํ•ด EntityManager#clear ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ

======
ํžˆ๋กœ1

์˜ค์ž‰. ์ด๋ฒˆ์—๋Š” ๋‚˜๊ฐ€์ง€ ์•Š์•˜๋‹ค.

 

EntityManager#clear ๊ฐ€ ํ…Œ์ŠคํŠธ์— ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์ด ์—†๋‚˜๋ณด๋‹ค ์‹ถ์—ˆ๋˜ ์ˆ˜์ •๋œ ๊ฐ€์„ค์ด ๋˜ ๋‹ค์‹œ ํ‹€๋ฆฐ ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์–ด๋–ค ์ฐจ์ด์ ์œผ๋กœ ์ธํ•ด ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋œ ๊ฒƒ์ผ๊นŒ?


 

์ •๋‹ต์€ findById ์™€ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์— ์žˆ๋‹ค.

 

MemberJpaRepository#findByTeam ์€ ์ง์ ‘ ์ƒˆ๋กญ๊ฒŒ ์ •์˜ํ•œ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์ด๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ findById ๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ํฌํ•จ๋˜๋Š”, ์ฆ‰ JPA ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ์ด๋‹ค.

๐Ÿธ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ๊ณผ์ •

๋‹ค์Œ ๋ฌธ์„œ์—์„œ ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ๋“ฏ์ด, JPA ์˜ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ JPQL ๋กœ ๋ณ€ํ™˜์ด ๋œ๋‹ค.

 

JPA Query Methods :: Spring Data JPA

 

JPA Query Methods :: Spring Data JPA

By default, Spring Data JPA uses position-based parameter binding, as described in all the preceding examples. This makes query methods a little error-prone when refactoring regarding the parameter position. To solve this issue, you can use @Param annotati

docs.spring.io

 

 

์˜ˆ๋ฅผ ๋“ค์–ด, findByLastnameOrFirstname ๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ–ˆ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ JPQL ์Šค๋‹ˆํŽซ์ด ๋œ๋‹ค.

… where x.lastname = ?1 or x.firstname = ?2

 

์ฆ‰, ์šฐ๋ฆฌ๊ฐ€ ์ •์˜ํ•œ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”์„œ๋“œ์˜ ํ˜•ํƒœ์—์„œ JPQL ๋กœ ๋ณ€ํ™˜์ด ๋˜๊ณ , ๊ทธ ์ดํ›„์— ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ๊ฐ€ ๋˜์–ด ์ตœ์ข…์ ์œผ๋กœ ์‹œํ–‰๋œ๋‹ค.

 

๐Ÿธ findById ์˜ ๋™์ž‘ ๋ฐฉ์‹

public Optional<T> findById(ID id) {
  Assert.notNull(id, "The given id must not be null");
  Class<T> domainType = this.getDomainClass();
  if (this.metadata == null) {
      return Optional.ofNullable(this.entityManager.find(domainType, id));
  } else {
      LockModeType type = this.metadata.getLockModeType();
      Map<String, Object> hints = this.getHints();
      return Optional.ofNullable(type == null ? this.entityManager.find(domainType, id, hints) : this.entityManager.find(domainType, id, type, hints));
  }
}

 

findById ๋Š” Hibernate ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ตฌํ˜„์ฒด์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ง์ ‘์ ์œผ๋กœ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, EntityManager ์˜ find ๋ฅผ ํ†ตํ•ด ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•ด์˜จ๋‹ค. ์ฆ‰, ์ฟผ๋ฆฌ๋ฅผ ๋ฐ”๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์šฐ์„ ์€ 1์ฐจ ์บ์‹œ๋ฅผ ํ™•์ธํ•˜๊ณ  ๊ทธ ์ดํ›„์— 1์ฐจ ์บ์‹œ์— ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ธ๋‹ค. ๊ทธ๋ž˜์„œ ์•ž์„œ์„œ entityManage.clear() ๋ฅผ ํ•ด์„œ 1์ฐจ ์บ์‹œ๋ฅผ ๋น„์šด ๊ฒฝ์šฐ์—๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ƒˆ์ง€๋งŒ, ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ด์ง€ ์•Š์•„๋„ ๋๋˜ ๊ฒƒ์ด๋‹ค.

๐Ÿธ ๊ทธ๋ž˜์„œ ์™œ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” 1์ฐจ ์บ์‹œ๋ฅผ ์•ˆ ๋ณด๋Š”๋ฐ?

findById ๋Š” 1์ฐจ ์บ์‹œ๋ฅผ ๋ณด๋Š” ๊ฒƒ์„ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ์™œ 1์ฐจ ์บ์‹œ๋ฅผ ๋ณด์ง€ ์•Š์„๊นŒ? ์–ด๋–ค ํŠน์„ฑ์— ์˜ํ•ด ๊ทธ๋Ÿฐ ๊ฒƒ์ผ๊นŒ?

 

์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋ผ์„œ ๋ผ๊ธฐ๋ณด๋‹ค๋Š” JPQL ์„ ํ†ตํ•ด ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

JPQL ์€ 1์ฐจ ์บ์‹œ๋ฅผ ๋ฐ”๋ผ๋ณด์ง€ ์•Š๋Š”๋‹ค. ์™œ ๊ทธ๋Ÿด๊นŒ?

1. ์–ด์ฐจํ”ผ ํšจ์œจ์ ์ด์ง€ ์•Š๋‹ค.

1์ฐจ ์บ์‹œ๋Š” Map ํ˜•ํƒœ๋กœ ์ €์žฅ์ด ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ Key ๋Š” Id ์ด๊ณ , Value ๋Š” ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์ด๋‹ค. ์ฆ‰, pk ๋ฅผ ํ†ตํ•ด 1์ฐจ ์บ์‹œ๋ฅผ ์กฐํšŒํ•˜๊ณ ์ž ํ•  ๋•Œ์—๋Š” ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด, ์–ด์ฐจํ”ผ ์ „์ฒด ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ „๋ถ€ ๋Œ์•„์•ผ ํ•˜๊ธฐ์— 1์ฐจ ์บ์‹œ๋ฅผ ๋ณด๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์ด์ ์„ ์ „ํ˜€ ์ฐพ์„ ์ˆ˜๊ฐ€ ์—†๋‹ค.

 

์ฆ‰, PK ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹ˆ๊ธฐ์— 1์ฐจ ์บ์‹œ๋ฅผ ๋ณด์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ ์„ค์ • ๊ฐ’์ธ ๊ฒƒ์ด๋‹ค.

2. ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ ๋ฌธ์ œ

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์กด์žฌํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ตœ์‹ ์ผ ๊ฒƒ์ด๋ผ๊ณ  ํ™•์ • ์ง€์„ ์ˆ˜๊ฐ€ ์—†๋‹ค.

 

๋งŒ์•ฝ, ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜ ๋‚ด๋ถ€์—์„œ ํŠน์ • ํŒ€์— ๋ฉค๋ฒ„๋ฅผ 3๋ช… ์ €์žฅํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

๊ทธ๋Ÿฌ๋ฉด ๊ทธ ํŒ€๊ณผ ๋ฉค๋ฒ„๋“ค์€ ๋ชจ๋‘ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์กด์žฌํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๊ณ  ํ•ด์„œ ํ•ด๋‹น ํŒ€์— ๋ฉค๋ฒ„๊ฐ€ ์ •๋ง ๊ทธ 3๋ช…๋งŒ ์กด์žฌํ• ๊นŒ?

 

๋‹ต์€ ๊ทธ๋Ÿด ์ˆ˜๋„ ์žˆ๊ณ , ์•„๋‹ ์ˆ˜๋„ ์žˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ํ™•์‹คํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋งค๋ฒˆ ์ฟผ๋ฆฌ๋ฅผ ์ง์ ‘์ ์œผ๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด๋‹ค.


 

๊ทธ๋ ‡๋‹ค๋ฉด ๋˜ ๋‹ค๋ฅธ ์˜๋ฌธ์ด ์ƒ๊ธด๋‹ค.

 

findById ์™€ ๊ฐ™์ด ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ƒ์„ฑ๋˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ JPA ์˜ 1์ฐจ ์บ์‹œ๋ฅผ ๊ฑฐ์ณ์„œ ์ฟผ๋ฆฌ๊ฐ€ ์•„์˜ˆ ๋‚˜๊ฐ€์ง€ ์•Š๋‚˜? 

๊ทธ๊ฑด ์‚ฌ์‹ค ๋˜ ์•„๋‹ˆ๋‹ค.

๐Ÿธ findAll ์˜ ๋™์ž‘ ๋ฐฉ์‹

findAll ์€ findById ์™€ ๊ฐ™์ด, ์ปดํŒŒ์ผ ํƒ€์ž„์— ์กด์žฌํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

 @Test
@DisplayName("๋ฉค๋ฒ„๋“ค์„ ์ „์ฒด ์กฐํšŒํ•œ๋‹ค")
void test4() {
    // given
    Team team = new Team("ํžˆ๋กœ์˜ ํŒ€");
    entityManager.persist(team);

    Member ํžˆ๋กœ1 = new Member("ํžˆ๋กœ1", team);
    entityManager.persist(ํžˆ๋กœ1);

    Member ํžˆ๋กœ2 = new Member("ํžˆ๋กœ2", team);
    entityManager.persist(ํžˆ๋กœ2);

    Member ํžˆ๋กœ3 = new Member("ํžˆ๋กœ3", team);
    entityManager.persist(ํžˆ๋กœ3);

    Member ํžˆ๋กœ4 = new Member("ํžˆ๋กœ4", team);
    entityManager.persist(ํžˆ๋กœ4);

    entityManager.flush();
    entityManager.clear();

    // then
    System.out.println("======");
    memberJpaRepository.findAll();
}

 

์œ„์™€ ๊ฐ™์ด ์—ฌ๋Ÿฌ ๋ฉค๋ฒ„๋“ค์„ ๋“ฑ๋กํ•˜๊ณ , ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.

======
Hibernate: 
    select
        m1_0.id,
        m1_0.name,
        m1_0.team_id 
    from
        member m1_0
Hibernate: 
    select
        t1_0.id,
        t1_0.name 
    from
        team t1_0 
    where
        t1_0.id=?

 

clear ๋ฅผ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์˜ ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

======
Hibernate: 
    select
        m1_0.id,
        m1_0.name,
        m1_0.team_id 
    from
        member m1_0

 

clear ๋ฅผ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฉค๋ฒ„๊ฐ€ ์ด๋ฏธ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์กด์žฌํ•˜๊ณ  ์žˆ์Œ์—๋„ Member ์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ”๋‹ค.

public List<T> findAll() {
	return this.getQuery((Specification)null, (Sort)Sort.unsorted()).getResultList();
}

 

๊ทธ ์ด์œ ๋Š” findAll ๋„ ์‚ฌ์‹ค์€ JPQL ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

getQuery(...)๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์€ ๊ฒฐ๊ตญ TypedQuery, ์ฆ‰ JPQL ๊ธฐ๋ฐ˜์˜ ์ฟผ๋ฆฌ ๊ฐ์ฒด์ด๋‹ค.


๐Ÿ˜ต ๊ทธ๋Ÿฌ๋ฉด EntityManager#clear ์™œ ํ•ด?

์œผ์•™~

 

EntityManager#clear ๋Š” ๋„๋Œ€์ฒด ์™œ ํ•˜๋Š”๊ฑธ๊นŒ?

๋Œ€๋ถ€๋ถ„์˜ ๋ฉ”์„œ๋“œ๋“ค์ด JPQL ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๊ณ , ๊ทธ๋ ‡๊ธฐ์— 1์ฐจ ์บ์‹œ๋ฅผ ๊ฑฐ์น˜์ง€๋„ ์•Š์„ํ…๋ฐ ๋ง์ด๋‹ค.

โœ… 1์ฐจ ์บ์‹œ์™€ ์ƒ๊ด€์—†์ด ์กฐํšŒ๋ฅผ ํ•˜๋”๋ผ๋„ ์ฐธ์กฐ๋Š” ํ•œ๋‹ค.

@Test
@DisplayName("clear ์—†์ด ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด, ์กฐํšŒ ๊ฒฐ๊ณผ๊ฐ€ ์‹ค์ œ DB์™€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค")
void test7() {
    // given
    Team team = new Team("ํžˆ๋กœ์˜ ํŒ€");
    entityManager.persist(team);

    Member member = new Member("ํžˆ๋กœ", team);
    entityManager.persist(member);
    entityManager.flush();

    // DB์— ๋ฐ˜์˜๋œ ์ƒํƒœ: name = "ํžˆ๋กœ"

    // when - DB์—๋Š” ๋ฐ˜์˜ํ•˜์ง€ ์•Š์•˜์ง€๋งŒ, ์—”ํ‹ฐํ‹ฐ ์ƒํƒœ๋งŒ ๋ณ€๊ฒฝ
    member.rename("ํžˆ๋กœ_์ˆ˜์ •");

    // then
    List<Member> results = memberJpaRepository.findByTeam(team);
    System.out.println(results.getFirst().getName());
}

 

์œ„์˜ ์ฝ”๋“œ์—์„œ member ์˜ ์ด๋ฆ„์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์—์„œ๋Š” ํžˆ๋กœ ์ด์ง€๋งŒ, ์—”ํ‹ฐํ‹ฐ ์ƒ์œผ๋กœ๋Š” 'ํžˆ๋กœ_์ˆ˜์ •' ์ด๋‹ค.

 

๊ทธ๋ ‡๊ธฐ์— ์œ„์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋Š” 'ํžˆ๋กœ'๊ฐ€ ๋˜์–ด์•ผ ๋งž๋‹ค.

'ํžˆ๋กœ_์ˆ˜์ •'์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์— ๋ฐ˜์˜์ด ๋˜์ง€ ์•Š์•˜๊ธฐ์— JPQL ์ด ๋ชจ๋ฅด๋Š” ์ •๋ณด์—ฌ์•ผ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๊ฒฐ๊ณผ๋Š” 'ํžˆ๋กœ_์ˆ˜์ •' ์ด ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

 

 

์™œ๋ƒํ•˜๋ฉด, JPQL ์€ 1์ฐจ ์บ์‹œ์™€ ์ƒ๊ด€์—†์ด ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๊ธด ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ฟผ๋ฆฌ๋ฅผ ๋งˆ์น˜๊ณ  ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ, 1์ฐจ ์บ์‹œ๋ฅผ ๋‹ค์‹œ ๋ณด๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

์ด ๊ณผ์ •์—์„œ ์ด๋ฏธ ๊ฒฐ๊ณผ์— ํ•ด๋‹นํ•˜๋Š” PK ๊ฐ€ 1์ฐจ ์บ์‹œ์— ์กด์žฌํ•œ๋‹ค๋ฉด ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜จ๋‹ค.

1 member ์˜ ์ฃผ์†Œ๊ฐ’

 

member ์˜ id ๊ฐ€ 1์ด๋ผ๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ ๊ตฌ์„ฑ๋˜์–ด์žˆ์„ ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ € member ์˜ ์ด๋ฆ„์€ 'ํžˆ๋กœ_์ˆ˜์ •'์ด ๋˜์–ด ์žˆ์„ ๊ฒƒ์ด๋‹ค.

 

id name team_id
1 ํžˆ๋กœ 1

 

JPQL ์ด ์กฐํšŒํ•ด ์˜จ ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋Š” ์œ„์™€ ๊ฐ™์•˜์„ ๊ฒƒ์ด๋‹ค.  pk ๋Š” 1์ด๊ณ , ์ด๋ฆ„์€ 'ํžˆ๋กœ_์ˆ˜์ •'์ด ์•„๋‹ˆ๋ผ 'ํžˆ๋กœ'์˜€์„ ๊ฒƒ์ด๋‹ค.

 

์—ฌ๊ธฐ์„œ JPQL ์˜ ์ฟผ๋ฆฌ ์กฐํšŒ ๊ฒฐ๊ณผ์™€ ์ƒ๊ด€์—†์ด 1์ฐจ ์บ์‹œ์— pk ๊ฐ€ 1์ธ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์กด์žฌํ•˜๊ธฐ์—, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒํ•ด ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ํ† ๋Œ€๋กœ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ๊ธฐ์กด์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์กด์žฌํ•˜๋Š” ๊ฐ’๋“ค์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

 

๊ทธ๋ž˜์„œ ๊ฒฐ๊ตญ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒํ•ด ์˜จ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹ˆ๋ผ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ† ๋Œ€๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

@Test
@DisplayName("clear ์—†์ด ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด, ์กฐํšŒ ๊ฒฐ๊ณผ๊ฐ€ ์‹ค์ œ DB์™€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค")
void test7() {
    // given
    Team team = new Team("ํžˆ๋กœ์˜ ํŒ€");
    entityManager.persist(team);

    Member member = new Member("ํžˆ๋กœ", team);
    entityManager.persist(member);
    entityManager.flush();

    // DB์— ๋ฐ˜์˜๋œ ์ƒํƒœ: name = "ํžˆ๋กœ"

    // when
    member.rename("ํžˆ๋กœ_์ˆ˜์ •");
    entityManager.clear();

    // DB์— ๋ฐ˜์˜๋œ ์ƒํƒœ: name = "ํžˆ๋กœ"

    // then
    List<Member> results = memberJpaRepository.findByTeam(team);
    System.out.println(results.getFirst().getName());
}

 

๋งŒ์•ฝ ์œ„์™€ ๊ฐ™์ด clear ๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด, ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์•„๋ฌด๋Ÿฐ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ์— ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ ํ† ๋Œ€๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.

flush ๋ฅผ ํ•œ ๊ฒƒ๋„ ์•„๋‹ˆ๊ธฐ์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์—์„œ๋Š” ์—ฌ์ „ํžˆ 'ํžˆ๋กœ'๋กœ ์กด์žฌํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •ํ™•ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ด๋ ‡๊ฒŒ EntityManager ์˜ clear ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ถ€์ •ํ•ฉ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

โœ… ์ฒ˜์Œ์œผ๋กœ ๋Œ์•„๊ฐ€์„œ ๋‹ค์‹œ ์งš์–ด๋ณด์ž

๋‚˜์˜ ์ฒซ ๊ฐ€์„ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•˜๋‹ค.

“EntityManager๋ฅผ clearํ•˜์ง€ ์•Š์œผ๋ฉด, ์‹ค์ œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ 1์ฐจ ์บ์‹œ์—์„œ ๊ฐ’์„ ์กฐํšŒํ•  ๊ฒƒ์ด๋‹ค.
๋”ฐ๋ผ์„œ ํ…Œ์ŠคํŠธ์˜ ์ •ํ™•๋„๋ฅผ ์œ„ํ•ด clear๊ฐ€ ํ•„์š”ํ•˜๋‹ค.”

 

ํ•˜์ง€๋งŒ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‚ฌ์‹ค์„ ์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

 

1. ํ•ญ์ƒ 1์ฐจ ์บ์‹œ๋งŒ์„ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

 

EntityManager.clear()๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„๋„, ์ƒํ™ฉ์— ๋”ฐ๋ผ ์‹ค์ œ ์ฟผ๋ฆฌ๊ฐ€ ๋‚ ์•„๊ฐ€๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.  

์ฆ‰, clear ์—ฌ๋ถ€๊ฐ€ ๋ฌด์กฐ๊ฑด ์ฟผ๋ฆฌ ์‹คํ–‰ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •์ง“์ง€๋Š” ์•Š๋Š”๋‹ค.

 

2. ํ…Œ์ŠคํŠธ์˜ ์ •ํ™•๋„๋Š” "์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋А๋ƒ" ๋งŒ์œผ๋กœ ๊ฒฐ์ •๋˜์ง€๋Š” ์•Š๋Š”๋‹ค.

 

์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜์—ˆ๋А๋ƒ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ, ๋” ์ค‘์š”ํ•œ ๊ฑด ๊ทธ ์ฟผ๋ฆฌ๊ฐ€ ์–ด๋–ค ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ€ ์–ด๋–ค ์ปจํ…์ŠคํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋А๋ƒ ์ด๋‹ค. ์ฆ‰, 1์ฐจ ์บ์‹œ์˜ ์˜ํ–ฅ๋ฟ ์•„๋‹ˆ๋ผ ์กฐํšŒ๋œ ๊ฐ์ฒด์˜ ์ƒํƒœ, flush ์—ฌ๋ถ€ ๋“ฑ๋„ ํ…Œ์ŠคํŠธ์˜ ์‹ ๋ขฐ๋„์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.

 

๊ฒฐ๊ตญ clear()๋Š” ๋‹จ์ˆœํžˆ ์ฟผ๋ฆฌ ์œ ๋ฌด๋ฅผ ํ†ต์ œํ•˜๊ธฐ ์œ„ํ•œ ์ˆ˜๋‹จ์ด๋ผ๊ธฐ๋ณด๋‹ค, ์—”ํ‹ฐํ‹ฐ์˜ ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ๋ช…ํ™•ํ•œ ํ…Œ์ŠคํŠธ ์กฐ๊ฑด์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ์ธ ๊ฒƒ์ด๋‹ค. 

 


โ˜€๏ธ ๊ฒฐ๋ก 

  • JPQL ์€ 1์ฐจ ์บ์‹œ์— ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์กด์žฌํ•˜๋”๋ผ๋„ ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฐ๋‹ค.
  • ์ฟผ๋ฆฌ๋Š” 1์ฐจ ์บ์‹œ์™€ ์—ฐ๊ด€์„ฑ์ด ์—†์ง€๋งŒ, ์กฐํšŒํ•ด์˜จ ๋’ค์— ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ์—๋Š” ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค.
  • EntityManager#clear ๋Š” 1์ฐจ ์บ์‹œ๋กœ ์ธํ•œ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ถ€์ •ํ•ฉ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.
  • ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๋А๋ƒ ์•„๋‹ˆ๋ƒ ๋งŒ์ด ํ…Œ์ŠคํŠธ์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ์š”์ธ์€ ์•„๋‹ˆ๋‹ค

โ˜€๏ธ ๋А๋‚€ ์ 

๊ฐœ์ธ์ ์œผ๋กœ ๋‚ด๋ฆฐ ๊ฒฐ๋ก ์€ ํ…Œ์ŠคํŠธ ๊ณผ์ •์—์„œ EntityManager#clear ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๋ ‡๊ฒŒ๊นŒ์ง€ ์ž˜๋ชป๋œ ์Šต๊ด€์€ ์•„๋‹Œ ๊ฒƒ ๊ฐ™๋‹ค.

์˜๋„์น˜ ์•Š์€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๊ณ , ์ •๋ง ํ…Œ์ŠคํŠธํ•˜๊ณ ์ž ํ•˜๋Š” ๋Œ€์ƒ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ์— ๋„์›€์ด ๋˜๊ธฐ๋Š” ํ•œ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜, ์ด์— ๋Œ€ํ•ด ๋ฌด์˜์‹์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ์•„๋‹Œ ๊ฒƒ์—๋Š” ๋ถ„๋ช…ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ ๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ๋ชฉ์ ์œผ๋กœ clear ๋ฅผ ํ•˜๋ ค๊ณ  ํ•˜๋Š”์ง€ ํ•œ๋ฒˆ ๋” ๋ฉˆ์ถฐ ์„œ์„œ JPA ์˜ ๋™์ž‘ ๋ฐฉ์‹์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ•ด๋ณธ๋‹ค๋ฉด ๋” ์ข‹์€ ๊ฐœ๋ฐœ์ž๋กœ ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ ํ•˜๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

 

๋ฌด์—‡์ด๋“  ๊ด€์Šต์ ์œผ๋กœ, ์ˆ˜๋™์ ์œผ๋กœ ๋ฐ›์•„๋“ค์ด์ง€ ๋ง์ž๋Š” ์ƒ๊ฐ์„ ๋‹ค์‹œ๊ธˆ ํ•˜๊ฒŒ ๋๋‹ค.