코드 그라데이션

단방향 연관관계 본문

Spring/JPA 공부

단방향 연관관계

완벽한 장면 2023. 8. 18. 09:42

연관관계 매핑 기초

- 객체가 지향하는 패러다임과 관계형 DB가 지향하는 패러다임이 서로 다르기 때문에 여기서 기인하는 어려움들이 있다.

 

학습목표

 

 

연관관계가 필요한 이유

‘객체지향 설계의 목표는 자율적인 객체들의
협력 공동체를 만드는 것이다.’

 

예제 시나리오

• 회원과 팀이 있다.
• 회원은 하나의 팀에만 소속될 수 있다.
• 회원과 팀은 다대일 관계다.

 

객체를 테이블에 맞추어 모델링(연관관계가 없는 객체)

 

Member

@Entity
@NoArgsConstructor
public class Member {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "MEMBER_ID")
  private Long id;

  @Column(name = "USERNAME")
  private String nane;

  @Column(name = "TEAM_ID")
  private Long teamId;
  //멤버와 팀을 레퍼런스로 가져가야 하는데 지금은 그냥 DB에 맞춰서 모델링을 한 것.


  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String usernane() {
    return nane;
  }

  public void setNane(String nane) {
    this.nane = nane;
  }

  public Long getTeamId() {
    return teamId;
  }

  public void setTeamId(Long teamId) {
    this.teamId = teamId;
  }
}

 

Team

@Entity
public class Team {

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

  private String name;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

 

 

JPAMain

public class JpaMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();

    try {
      //팀 저장
      Team team = new Team();
      team.setName("TeamA");
      em.persist(team);

      //회원 저장
      Member member = new Member();
      member.setNane("member1");
      member.setTeamId(team.getId()); // member.setTeam(); 이 아니다.
      em.persist(member);

      tx.commit();
    } catch (Exception e) {
      tx.rollback();
    } finally {
      em.close();
    }
    emf.close();
  }
}

 

 

실행 결과

11:53:56.144 [main] DEBUG org.hibernate.SQL - 
    call next value for hibernate_sequence
Hibernate: 
    call next value for hibernate_sequence
11:53:56.149 [main] DEBUG org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 1
11:53:56.149 [main] DEBUG org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered
11:53:56.153 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 1, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
11:53:56.168 [main] DEBUG org.hibernate.SQL - 
    call next value for hibernate_sequence
Hibernate: 
    call next value for hibernate_sequence
11:53:56.170 [main] DEBUG org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 2
11:53:56.170 [main] DEBUG org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered
11:53:56.170 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 2, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
11:53:56.170 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - committing
11:53:56.171 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Processing flush-time cascades
11:53:56.172 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Dirty checking collections
11:53:56.178 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 2 insertions, 0 updates, 0 deletions to 2 objects
11:53:56.178 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
11:53:56.179 [main] DEBUG org.hibernate.internal.util.EntityPrinter - Listing entities:
11:53:56.179 [main] DEBUG org.hibernate.internal.util.EntityPrinter - inflearn.exjpa.jpaExample.Team{name=TeamA, id=1}
11:53:56.179 [main] DEBUG org.hibernate.internal.util.EntityPrinter - inflearn.exjpa.jpaExample.Member{teamId=1, nane=member1, id=2}
11:53:56.186 [main] DEBUG org.hibernate.SQL - 
    /* insert inflearn.exjpa.jpaExample.Team
        */ insert 
        into
            Team
            (name, TEAM_ID) 
        values
            (?, ?)
Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Team
        */ insert 
        into
            Team
            (name, TEAM_ID) 
        values
            (?, ?)
11:53:56.191 [main] DEBUG org.hibernate.SQL - 
    /* insert inflearn.exjpa.jpaExample.Member
        */ insert 
        into
            Member
            (USERNAME, TEAM_ID, MEMBER_ID) 
        values
            (?, ?, ?)
Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Member
        */ insert 
        into
            Member
            (USERNAME, TEAM_ID, MEMBER_ID) 
        values
            (?, ?, ?)
11:53:56.196 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
11:53:56.197 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
11:53:56.197 [main] DEBUG org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl - HHH000420: Closing un-released batch
11:53:56.198 [main] DEBUG org.hibernate.internal.SessionFactoryImpl - HHH000031: Closing
11:53:56.198 [main] DEBUG org.hibernate.type.spi.TypeConfiguration$Scope - Un-scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration$Scope@2a369e14] from SessionFactory [org.hibernate.internal.SessionFactoryImpl@38f2e97e]
11:53:56.198 [main] DEBUG org.hibernate.service.internal.AbstractServiceRegistryImpl - Implicitly destroying ServiceRegistry on de-registration of all child ServiceRegistries
11:53:56.198 [main] INFO org.hibernate.orm.connections.pooling - HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test]
11:53:56.201 [main] DEBUG org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl - Implicitly destroying Boot-strap registry on de-registration of all child ServiceRegistries

종료 코드 0(으)로 완료된 프로세스

 

 

콘솔 들어가보면

 

만약 멤버를 찾아서 어떤 팀인지 알고 싶다면

try {
      //팀 저장
      Team team = new Team();
      team.setName("TeamA");
      em.persist(team);

      //회원 저장
      Member member = new Member();
      member.setNane("member1");
      member.setTeamId(team.getId()); // member.setTeam(); 이 아니다.
      em.persist(member);
      
      // 여기
      Member findMember = em.find(Member.class, member.getId());
      
      Long findTeamId = findMember.getTeamId();;;
      Team findTeam = em.find(Team.class, findTeamId); 

      tx.commit();
    } catch (Exception e) {
      tx.rollback();
    } finally {
      em.close();
    }

 

// 여기 

부부도 추가해줘야함. 번거로움.

연관관계가 설정되어있지 않기 때문

객체지향스럽지 않은 방식임.

 

 

객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다.

• 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
• 객체는 참조를 사용해서 연관된 객체를 찾는다.
• 테이블과 객체 사이에는 이런 큰 간극이 있다.

 

 


단방향 연관관계

 

객체 지향 모델링으로 바꾸면

객체 지향 모델링(객체 연관관계 사용)

 

객체 지향 모델링(객체의 참조와 테이블의 외래 키를 매핑)

Member 클래스 변경

  @ManyToOne
  @JoinColumn(name = "TEAM_ID")
  private Team team;
  //Member 입장에서는 여러 멤버가 하나의 팀에 소속될 수 있으므로.
  // 그리고 객체에 있는 Team team;레퍼런스랑. Member 테이블의 TEAM_ID(FK)랑 매핑을 해야.

 

객체 지향 모델링(ORM 매핑)

 

JpaMain

public class JpaMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();

    try {
      //팀 저장
      Team team = new Team();
      team.setName("TeamA");
      em.persist(team);

      //회원 저장
      Member member = new Member();
      member.setNane("member1");
      member.setTeam(team);
      // 이러면 Jpa가 팀에서 알아서 pk값을 꺼내서 Insert할 때 FK 값으로 사용한다.

      em.persist(member);


      // 조회할 때도 단순해짐
      Member findMember = em.find(Member.class, member.getId());
      // 1차캐시에서 가져오는 것 잊어버리지 말기

      Team findTeam = findMember.getTeam();
      System.out.println("팀찾기 = " + findTeam.getName());
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
    } finally {
      em.close();
    }
    emf.close();
  }
}

 

실행 결과

//윗부분 생략
12:14:49.368 [main] DEBUG org.hibernate.SQL - 
    
    drop table if exists Member CASCADE 
Hibernate: 
    
    drop table if exists Member CASCADE 
12:14:49.370 [main] INFO org.hibernate.orm.connections.access - HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@1894593a] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
12:14:49.371 [main] DEBUG org.hibernate.SQL - 
    
    drop table if exists Team CASCADE 
Hibernate: 
    
    drop table if exists Team CASCADE 
12:14:49.372 [main] DEBUG org.hibernate.SQL - 
    
    drop sequence if exists hibernate_sequence
Hibernate: 
    
    drop sequence if exists hibernate_sequence
12:14:49.375 [main] DEBUG org.hibernate.SQL - create sequence hibernate_sequence start with 1 increment by 1
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
12:14:49.376 [main] INFO org.hibernate.orm.connections.access - HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@67f3d192] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
12:14:49.377 [main] DEBUG org.hibernate.SQL - 
    
    create table Member (
       MEMBER_ID bigint not null,
        USERNAME varchar(255),
        TEAM_ID bigint,
        primary key (MEMBER_ID)
    )
Hibernate: 
    
    create table Member (
       MEMBER_ID bigint not null,
        USERNAME varchar(255),
        TEAM_ID bigint,
        primary key (MEMBER_ID)
    )
12:14:49.379 [main] DEBUG org.hibernate.SQL - 
    
    create table Team (
       TEAM_ID bigint not null,
        name varchar(255),
        primary key (TEAM_ID)
    )
Hibernate: 
    
    create table Team (
       TEAM_ID bigint not null,
        name varchar(255),
        primary key (TEAM_ID)
    )
12:14:49.380 [main] DEBUG org.hibernate.SQL - 
    
    alter table Member 
       add constraint FKl7wsny760hjy6x19kqnduasbm 
       foreign key (TEAM_ID) 
       references Team
Hibernate: 
    
    alter table Member 
       add constraint FKl7wsny760hjy6x19kqnduasbm 
       foreign key (TEAM_ID) 
       references Team
12:14:49.388 [main] DEBUG org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator - No JtaPlatform was specified, checking resolver
12:14:49.388 [main] DEBUG org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator - No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver]
12:14:49.393 [main] DEBUG org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver - Could not resolve JtaPlatform, using default [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
12:14:49.393 [main] INFO org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
12:14:49.398 [main] DEBUG org.hibernate.service.internal.SessionFactoryServiceRegistryImpl - EventListenerRegistry access via ServiceRegistry is deprecated.  Use `sessionFactory.getEventEngine().getListenerRegistry()` instead
12:14:49.399 [main] DEBUG org.hibernate.hql.internal.QueryTranslatorFactoryInitiator - QueryTranslatorFactory: org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory@45404d5
12:14:49.405 [main] DEBUG org.hibernate.query.spi.NamedQueryRepository - Checking 0 named HQL queries
12:14:49.405 [main] DEBUG org.hibernate.query.spi.NamedQueryRepository - Checking 0 named SQL queries
12:14:49.406 [main] DEBUG org.hibernate.internal.SessionFactoryRegistry - Initializing SessionFactoryRegistry : org.hibernate.internal.SessionFactoryRegistry@44b194fe
12:14:49.408 [main] DEBUG org.hibernate.internal.SessionFactoryRegistry - Registering SessionFactory: 8e819d61-fea0-404b-bfa7-ef1602395caf (<unnamed>)
12:14:49.408 [main] DEBUG org.hibernate.internal.SessionFactoryRegistry - Not binding SessionFactory to JNDI, no JNDI name configured
12:14:49.466 [main] DEBUG org.hibernate.stat.internal.StatisticsInitiator - Statistics initialized [enabled=false]
12:14:49.473 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
12:14:49.473 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - begin
12:14:49.478 [main] DEBUG org.hibernate.SQL - 
    call next value for hibernate_sequence
Hibernate: 
    call next value for hibernate_sequence
12:14:49.483 [main] DEBUG org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 1
12:14:49.483 [main] DEBUG org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered
12:14:49.487 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 1, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
12:14:49.499 [main] DEBUG org.hibernate.SQL - 
    call next value for hibernate_sequence
Hibernate: 
    call next value for hibernate_sequence
12:14:49.501 [main] DEBUG org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 2
12:14:49.501 [main] DEBUG org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered
12:14:49.501 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 2, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
팀찾기 = TeamA
12:14:49.510 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - committing
12:14:49.510 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Processing flush-time cascades
12:14:49.511 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Dirty checking collections
12:14:49.518 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 2 insertions, 0 updates, 0 deletions to 2 objects
12:14:49.518 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
12:14:49.520 [main] DEBUG org.hibernate.internal.util.EntityPrinter - Listing entities:
12:14:49.520 [main] DEBUG org.hibernate.internal.util.EntityPrinter - inflearn.exjpa.jpaExample.Team{name=TeamA, id=1}
12:14:49.520 [main] DEBUG org.hibernate.internal.util.EntityPrinter - inflearn.exjpa.jpaExample.Member{nane=member1, id=2, team=inflearn.exjpa.jpaExample.Team#1}
12:14:49.526 [main] DEBUG org.hibernate.SQL - 
    /* insert inflearn.exjpa.jpaExample.Team
        */ insert 
        into
            Team
            (name, TEAM_ID) 
        values
            (?, ?)
Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Team
        */ insert 
        into
            Team
            (name, TEAM_ID) 
        values
            (?, ?)
12:14:49.530 [main] DEBUG org.hibernate.SQL - 
    /* insert inflearn.exjpa.jpaExample.Member
        */ insert 
        into
            Member
            (USERNAME, TEAM_ID, MEMBER_ID) 
        values
            (?, ?, ?)
Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Member
        */ insert 
        into
            Member
            (USERNAME, TEAM_ID, MEMBER_ID) 
        values
            (?, ?, ?)
12:14:49.536 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
12:14:49.536 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
12:14:49.537 [main] DEBUG org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl - HHH000420: Closing un-released batch
12:14:49.537 [main] DEBUG org.hibernate.internal.SessionFactoryImpl - HHH000031: Closing
12:14:49.537 [main] DEBUG org.hibernate.type.spi.TypeConfiguration$Scope - Un-scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration$Scope@2cc75074] from SessionFactory [org.hibernate.internal.SessionFactoryImpl@294bdeb4]
12:14:49.538 [main] DEBUG org.hibernate.service.internal.AbstractServiceRegistryImpl - Implicitly destroying ServiceRegistry on de-registration of all child ServiceRegistries
12:14:49.538 [main] INFO org.hibernate.orm.connections.pooling - HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test]
12:14:49.540 [main] DEBUG org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl - Implicitly destroying Boot-strap registry on de-registration of all child ServiceRegistries

종료 코드 0(으)로 완료된 프로세스

팀이 TeamA 나온다.

 

영속성 컨텍스트 말고 db에서 가져온 쿼리 보고싶어 하면

전략
	try {
      //팀 저장
      Team team = new Team();
      team.setName("TeamA");
      em.persist(team);

      //회원 저장
      Member member = new Member();
      member.setNane("member1");
      member.setTeam(team);
      // 이러면 Jpa가 팀에서 알아서 pk값을 꺼내서 Insert할 때 FK 값으로 사용한다.

      em.persist(member);
      
      // 여기 추가
      em.flush();
      em.clear();
      


      // 조회할 때도 단순해짐
      Member findMember = em.find(Member.class, member.getId());
      // 1차캐시에서 가져오는 것 잊어버리지 말기

      Team findTeam = findMember.getTeam();
      System.out.println("팀찾기 = " + findTeam.getName());
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
    } finally {
      em.close();
    }
    
    후략

 

em.flush(); 해서 영속성 컨텍스트에 있는 것을 DB에 다 쿼리를 날려버리고 싱크를 맞춘 다음에

em.clear(); 로 영속성 컨텍스트를 다 초기화 시켜버리는 것.

 

실행 결과

12:23:20.028 [main] DEBUG org.hibernate.SQL - 
    call next value for hibernate_sequence
Hibernate: 
    call next value for hibernate_sequence
12:23:20.035 [main] DEBUG org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 1
12:23:20.035 [main] DEBUG org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered
12:23:20.037 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 1, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
12:23:20.054 [main] DEBUG org.hibernate.SQL - 
    call next value for hibernate_sequence
Hibernate: 
    call next value for hibernate_sequence
12:23:20.055 [main] DEBUG org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 2
12:23:20.055 [main] DEBUG org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered
12:23:20.055 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 2, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
12:23:20.056 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Processing flush-time cascades
12:23:20.057 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Dirty checking collections
12:23:20.061 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 2 insertions, 0 updates, 0 deletions to 2 objects
12:23:20.061 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
12:23:20.062 [main] DEBUG org.hibernate.internal.util.EntityPrinter - Listing entities:
12:23:20.062 [main] DEBUG org.hibernate.internal.util.EntityPrinter - inflearn.exjpa.jpaExample.Team{name=TeamA, id=1}
12:23:20.062 [main] DEBUG org.hibernate.internal.util.EntityPrinter - inflearn.exjpa.jpaExample.Member{nane=member1, id=2, team=inflearn.exjpa.jpaExample.Team#1}
12:23:20.068 [main] DEBUG org.hibernate.SQL - 
    /* insert inflearn.exjpa.jpaExample.Team
        */ insert 
        into
            Team
            (name, TEAM_ID) 
        values
            (?, ?)
Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Team
        */ insert 
        into
            Team
            (name, TEAM_ID) 
        values
            (?, ?)
12:23:20.073 [main] DEBUG org.hibernate.SQL - 
    /* insert inflearn.exjpa.jpaExample.Member
        */ insert 
        into
            Member
            (USERNAME, TEAM_ID, MEMBER_ID) 
        values
            (?, ?, ?)
Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Member
        */ insert 
        into
            Member
            (USERNAME, TEAM_ID, MEMBER_ID) 
        values
            (?, ?, ?)
12:23:20.094 [main] DEBUG org.hibernate.SQL - 
    select
        member0_.MEMBER_ID as member_i1_0_0_,
        member0_.USERNAME as username2_0_0_,
        member0_.TEAM_ID as team_id3_0_0_,
        team1_.TEAM_ID as team_id1_1_1_,
        team1_.name as name2_1_1_ 
    from
        Member member0_ 
    left outer join
        Team team1_ 
            on member0_.TEAM_ID=team1_.TEAM_ID 
    where
        member0_.MEMBER_ID=?
Hibernate: 
    select
        member0_.MEMBER_ID as member_i1_0_0_,
        member0_.USERNAME as username2_0_0_,
        member0_.TEAM_ID as team_id3_0_0_,
        team1_.TEAM_ID as team_id1_1_1_,
        team1_.name as name2_1_1_ 
    from
        Member member0_ 
    left outer join
        Team team1_ 
            on member0_.TEAM_ID=team1_.TEAM_ID 
    where
        member0_.MEMBER_ID=?
12:23:20.104 [main] DEBUG org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl - On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified
12:23:20.114 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving attributes for [inflearn.exjpa.jpaExample.Member#2]
12:23:20.114 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `nane` : value = member1
12:23:20.114 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`nane`)  - enhanced for lazy-loading? - false
12:23:20.114 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `team` : value = 1
12:23:20.114 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`team`)  - enhanced for lazy-loading? - false
12:23:20.115 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [inflearn.exjpa.jpaExample.Member#2]
12:23:20.115 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving attributes for [inflearn.exjpa.jpaExample.Team#1]
12:23:20.115 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `name` : value = TeamA
12:23:20.115 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`name`)  - enhanced for lazy-loading? - false
12:23:20.115 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [inflearn.exjpa.jpaExample.Team#1]
12:23:20.116 [main] DEBUG org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader - Done entity load : inflearn.exjpa.jpaExample.Member#2
팀찾기 = TeamA
12:23:20.116 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - committing
12:23:20.116 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Processing flush-time cascades
12:23:20.117 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Dirty checking collections
12:23:20.117 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 0 insertions, 0 updates, 0 deletions to 2 objects
12:23:20.117 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
12:23:20.117 [main] DEBUG org.hibernate.internal.util.EntityPrinter - Listing entities:
12:23:20.117 [main] DEBUG org.hibernate.internal.util.EntityPrinter - inflearn.exjpa.jpaExample.Team{name=TeamA, id=1}
12:23:20.117 [main] DEBUG org.hibernate.internal.util.EntityPrinter - inflearn.exjpa.jpaExample.Member{nane=member1, id=2, team=inflearn.exjpa.jpaExample.Team#1}
12:23:20.118 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
12:23:20.118 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
12:23:20.119 [main] DEBUG org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl - HHH000420: Closing un-released batch
12:23:20.119 [main] DEBUG org.hibernate.internal.SessionFactoryImpl - HHH000031: Closing
12:23:20.119 [main] DEBUG org.hibernate.type.spi.TypeConfiguration$Scope - Un-scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration$Scope@37468787] from SessionFactory [org.hibernate.internal.SessionFactoryImpl@5300f14a]
12:23:20.119 [main] DEBUG org.hibernate.service.internal.AbstractServiceRegistryImpl - Implicitly destroying ServiceRegistry on de-registration of all child ServiceRegistries
12:23:20.119 [main] INFO org.hibernate.orm.connections.pooling - HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test]
12:23:20.121 [main] DEBUG org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl - Implicitly destroying Boot-strap registry on de-registration of all child ServiceRegistries

종료 코드 0(으)로 완료된 프로세스

    left outer join
        Team team1_ 
            on member0_.TEAM_ID=team1_.TEAM_ID 

 

이렇게 조인해서 가져왔다는 것을 확인할 수 있음.

 


연관관계 수정 시

이렇게 가능함.

728x90
Comments