@Entity(name = "USERs")
@Setter
@Getter
@ToString
public class User {
@Id @GeneratedValue
@Column(name = "USER_ID")
private Long id;
private String username;
}
@Entity
@Setter
@Getter
@ToString
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String teamname;
}
@OneToMany 단방향
1:M관계에서는 연관관계의 주인이 1쪽으로 잡혀버린다.
외래키 자체는 M쪽에 존재하는데 외래키를 M이 관리하지 않고 1이 관리하게 된다.
@JoinColumn("연관관계 1 엔티티 PK") 여기서 말하는 pk는 자기자신을 가리킨다.
List 즉 M형태의 컬렉션 타입 필드를 선언해준다.
@OneToMany
@JoinColumn(name = "TEAM_ID")
private List<User> users = new ArrayList<>();
1에서 M 즉, Team에서 User에 존재하는 TEAM_ID 외래키를 관리해야 하는데
데이터베이스 테이블에는 M쪽에 FK가 생성이되지만
M의 Entity에는 필드로서 존재하지 않기 때문에 그것에 대한 관리 자체를 M쪽에서 할 수 가 없게된다.
따라서 1에 선언한 컬렉션에 M 객체를 추가해 줘야만 JPA가 인식하고 FK를 관리할 수 있게 된다.
@SpringBootTest
@Transactional
public class JpaTest {
@PersistenceContext
EntityManager em;
@Test
public void OneToXTest() {
User user = new User();
user.setUsername("userA");
em.persist(user);
Team team = new Team();
team.setTeamname("teamA");
team.getUsers().add(user); // DB 관점에서 User에 team_id 외래키가 추가되고 Update쿼리를 통해 관리된다.
em.persist(team);
em.flush();
em.clear();
User findUser = em.find(User.class, user.getId());
System.out.println("findUser = " + findUser);
Team findTeam = em.find(Team.class, team.getId());
System.out.println("findTeam = " + findTeam);
System.out.println("findTeam.getUsers() = " + findTeam.getUsers());
}
}
[콘솔 출력 내용]
update
users
set
team_id=2
where
user_id=1
이때 FK에 대한 관리는 insert쿼리로 나가지 않고 update 쿼리를 통해 관리된다.
update쿼리가 나가는 이유는 앞서 설명한대로, M:1관계에서는 M쪽에 1에대한 정보를 세팅해줌으로써 FK가 관리가 되는데, M쪽에 FK 관리를 할 수 없기 때문에 1에대한 정보를 세팅할 수가 없게 된다.
team.getUsers().add(user);
결과적으로 위 코드와 같이 컬렉션에 m 객체를 추가함으로써 JPA에서는 추가된 m 객체에 현재 1 의 대상 외래키값을 Update 처리하는걸로 이해할 수 있겠다.
@OneToMany 양방향
JPA 스펙상 공식적으로 존재하지 않지만 가능은 하다.
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false) //JPA가 인식하고
private Team team;
User 객체에서 team객체를 Team 객체의 TEAM_ID PK기준으로 ForeignKey 연관관계 매핑은 하되,
insert와 update를 하지않는 읽기전용 필드로만 지정하는것이다.
앞서 ManyToOne 단방향에서 Team을 연관관계의 주인으로 만들었고, 위 같이 선언하게 되면 User에도 연관관계의 주인처럼 만들었지만, 읽기 전용으로 설정해버린것이다.
이렇게 되버리면 사실상 양방향 매핑한 것과 똑같이 된다.
관리는 Team으로 하고 User에서도 읽기가 가능하도록
JPA스펙상 1:M 양방향 관계는 공식적으로 존재하지 않지만 위와 같이 설정할 수 있다.
실무에서 복잡하게 하다 보면 위와 같이 OneToMany 양방향을 통해 One에서 읽을 수 있도록 설정하는 전략이 한번씩 필요할 때가 있다.
'Hibernate > JPA(EntityManager)' 카테고리의 다른 글
[JPA] @ManyToMany와 한계점 극복 (0) | 2023.06.29 |
---|---|
[JPA] @OneToOne 단방향/양방향 - 외래키 정책 기준 (1) | 2023.06.29 |
[JPA] @ManyToOne 단방향 / @ManyToOne <=> @OneToMany 양방향 정리 (0) | 2023.06.28 |
[JPA] JPQL 및 queryDSL 사용자정의 함수 등록법 (MySql) (0) | 2023.06.21 |
JPA EntityManager - Entity 기본 구현 및 SELECT, INSERT, UPDATE, DELETE (0) | 2023.04.15 |