코드 그라데이션
단방향 연관관계 본문
연관관계 매핑 기초
- 객체가 지향하는 패러다임과 관계형 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
'Spring > JPA 공부' 카테고리의 다른 글
실전 예제 - 2. 연관관계 매핑 시작 (0) | 2023.08.19 |
---|---|
양방향 연관관계와 연관관계의 주인 (0) | 2023.08.19 |
실전 예제 1 - 요구사항 분석과 기본 매핑 (0) | 2023.08.17 |
<보충설명> 기본키 매핑 (0) | 2023.08.16 |
엔티티 매핑 4 - 기본키 매핑 (0) | 2023.08.16 |
Comments