์ต๊ทผ์ ์๋ฒ ๊ฐ๋ฐ์ ํ๋ ์์ค์.. ํฐ ์ค์๋ฅผ ์ ์ง๋ฌ ๋ฒ๋ ธ๋ค.
์๋ฒ์ ๊ตฌ์ฑ ์๊ฑด์ด ์๋์ ๊ฐ์๋ค.
1. ์๋ฒ๊ฐ ์ฌ๋ฌ ๊ฐ์ ์ธ์คํด์ค์์ ๋์ํ๋ ๊ฒ์ ๊ฐ์
2. ๋์๋ค๋ฐ์ ์ธ ์์ฒญ์๋ ๋ฌธ์ ๊ฐ ์๋๋ก ์ค๊ณ
์ฌ๊ธฐ์์ 1๋ฒ์ ์ด๋์ ๋ ๊ฐ์์ ํ์ง๋ง 2๋ฒ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํด์ผ ํ ์ง ์๊ฐ์ง๋ ๋ชปํ๋ค
์๋ ์ฌ๋์๊ฒ๋ ๋ณด์ด๊ฒ ์ง๋ง.. ๋ด๊ณต์ด ๋ถ์กฑํ์ฌ ๋ชป๋ณด๊ณ ์ง๋๊ฐ๋ ํ์ธ๊ฒ ๊ฐ๋ค..
์ด๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด์๋ Database์ ๋์์ฑ์ ํด๊ฒฐํด์ผ ํ๋๋ฐ
1. Read/Write์์ Lock์ ๊ฑธ์ด์ฃผ๊ฑฐ๋
2. insert / update query๋ฅผ ํ ๋ database ๋ฅผ ๋ฐ๋ก ์ฐธ์กฐํ๋๋ก ํด์ผ ํ๋ ๊ฒ์ด์๋ค.
์ฆ, Controller๊ฐ ์ฌ์ฉํ๋ Service function์์
@Transactional์ด ๊ฑธ๋ ค์๋ค๊ณ ํด์ Database์ ๋์์ฑ์ ๋ง์กฑํ ์ ์๊ณ ,
๋ณ๋์ ์ค์ ์ ํด ์ฃผ๊ฑฐ๋ Query๋ฅผ ๋ ๋ ค์ผ ํ๋ ๊ฒ์ด์๋ค.
Entity๊ตฌ์ฑ์ ๋ค์๊ณผ ๊ฐ๋ค
@Entity
class Team(
var title: String,
) {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // DB์์ ์๋์ผ๋ก ID increment
@Column(name = "team_id")
var id: Long = 0L
// Onwer Entity๋ฅผ Player๋ก ์ง์ , Lazy type fetch, Persistence ์ ์ด ํ์
@OneToMany(mappedBy="team", cascade=[CascaseType.ALL], fetch = FetchType.LAZY)
var players : MutableList<Player> = mutableListOf()
}
@Entity
class Player(
var name : String,
@ManyToOne
@JoinColumn(name = "team_id") // ์ธ๋ํค ๋งคํ์ ์ํ ์ค์
var game: Game
) {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // DB์์ ์๋์ผ๋ก ID increment
@Column(name = "player_id")
var id: Long = 0L
var count : Long
}
Game <--> Player ์ํฐํฐ๊ฐ 1:N์ผ๋ก ์ค์ ๋์ด ์๋ค.
Game์ด MappedBy๋ฅผ Player์ "team" field๋ก ๋ช ์ ํด ์ค์ผ๋ก์จ Player๊ฐ Owner๋ก ๋ฑ๋ก.
Player table์ ๋ํด์๋ ์๋ Query๋ฌธ๊ณผ ๊ฐ์ด Foreign Key๋ฅผ ์์ฑํ๊ฒ ๋๋ค.
alter table player add constraint FKdvd6ljes11r44igawmpm1mc5s foreign key (team_id) references team
์ฌ๊ธฐ์์ Player ์์ฑ ์ Team์ total_player_number๋ฅผ ์๊ฐํด๋ณด์.
๋น์ฐํ ํ๋ ์ด์ด๊ฐ ์์ฑ๋ ๋ ๋ง๋ค 1์ฉ ์ฆ๊ฐ๋์ด์ผ ํ ๊ฒ์ด๋ค.
ํ์ง๋ง, ์ฌ๋ฌ Client๊ฐ ๋์์ Player๋ฅผ ์์ฑํ๊ณ , Database๊ฐ Lock์ด ๋์ง ์์๋๋ฅผ ๊ฐ์ ํด๋ณด์.
2๊ฐ์ Client์์ ๊ฐ๊ฐ Player๋ฅผ ์์ฑํ๋ ค๊ณ ํ๋ค.
๋ํ, ๊ฐ๊ฐ์ Client์์ Team ์ ๋ณด๋ฅผ ์ฝ์ ๋ total_player_number๊ฐ 0์ด์๋ค.
์ด ๋, ๋์์ request๊ฐ ๋ฐ์ํ๊ฒ ๋๋ฉด 2๊ฐ์ Player๊ฐ ์์ฑ๋์์ง๋ง
Team์ total_player_number๋ 1์ด ๋ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํ๋ค.
์ฒซ๋ฒ์งธ Player๋ก ์ธํด total_player_number๊ฐ 1๋ก ์ฆ๊ฐํ์ง๋ง,
๋๋ฒ ์งธ Player ์ ์ฅ ๋น์ ์ด๋ฏธ ์ฝ์ด์จ team์ ํด๋น ํ๋ ๊ฐ์ด 0์ด๊ธฐ ๋๋ฌธ์
1 -> 2๋ก ๋ณํ๋ ๊ฒ์ด ์๋๋ผ 1 -> 1๋ก ๋ฎ์ด์์ ์ง ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋์์ฑ์ ๊ณ ๋ คํ์ง ์์์ ๋ Query ๋ฌธ
select
team0_.team_id as team_id1_3_0_,
team0_.name as name2_3_0_,
team0_.total_player_number as total_pl3_3_0_,
players1_.team_id as team_id4_1_1_,
players1_.player_id as player_i1_1_1_,
players1_.player_id as player_i1_1_2_,
players1_.count as count2_1_2_,
players1_.name as name3_1_2_,
players1_.team_id as team_id4_1_2_
from
team team0_
left outer join
player players1_
on
team0_.team_id=players1_.team_id
where team0_.team_id=?
insert into player
(player_id, count, name, team_id)
values
(null, ?, ?, ?)
update team
set
name=?,
total_player_number=?
where
team_id=?
Team repository๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํด์ Pessimistic Lock์ ๊ฑธ์ด์ฃผ์๋ค.
interface TeamRepository : JpaRepository<Team, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE) // ๋น๊ด์ Lock (Read / Write ๋ชจ๋)
@EntityGraph(attributePaths = ["players"])
override fun findById(id: Long): Optional<Team>
}
๋์์ฑ์ ๊ณ ๋ คํ์ ๋ Query ๋ฌธ
select
team0_.team_id as team_id1_3_0_,
team0_.name as name2_3_0_,
team0_.total_player_number as total_pl3_3_0_,
players1_.team_id as team_id4_1_1_,
players1_.player_id as player_i1_1_1_,
players1_.player_id as player_i1_1_2_,
players1_.count as count2_1_2_,
players1_.name as name3_1_2_,
players1_.team_id as team_id4_1_2_
from
team team0_
left outer join
player players1_
on
team0_.team_id=players1_.team_id
where
team0_.team_id=?
for update /* Database lock์ ์ํด for update ๋ผ๋ ๊ตฌ๋ฌธ์ด ์ถ๊ฐ ๋จ */
insert into player
(player_id, count, name, team_id)
values
(null, ?, ?, ?)
update team
set
name=?,
total_player_number=?
where
team_id=?
๋ค๋ฅธ๊ฑด ๋์ผํ์ง๋ง, select ๋ฌธ์์ ๋ค์ ~ for update ๊ฐ ๋ถ์ด์๋ค.
์ด๋ ๋์์ฑ ์ ์ด๋ฅผ ์ํด ํน์ row์ READ / WRITE Lock์ด ๊ฑธ๋ ค์๋ค๋ ๋ง์ด๋ค (๋ฐฐํ์ Lock).
๋ง์ฝ, Read๋ ์์ ๋กญ๊ฒ ํ๋, Write์์๋ง Lock์ ๊ฑธ๊ณ ์ถ๋ค๋ฉด PESSIMISTIC_READ ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
๋ค์ ํฌ์คํ ์์ ์ง์ ํ ์คํธ๋ฅผ ํด๋ณด๋๋ก ํ๊ฒ ๋ค.
'Coding > SpringBoot' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SpringBoot] Kotlin - Entity Graph (1) | 2021.04.22 |
---|