Back-End/JPA

์—”ํ‹ฐํ‹ฐ(Entity) ํ…Œ์ด๋ธ”(Table) ๋งคํ•‘

@deveely 2018. 11. 30. 10:47
๋ฐ˜์‘ํ˜•

๐Ÿงฉ JPA ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘๊ณผ ๊ธฐ๋ณธ ํ‚ค ์ „๋žต ์ •๋ฆฌ

์ •๋ฆฌ ๊ธฐ์ค€: ใ€Ž์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐใ€ ํ•™์Šต ๋‚ด์šฉ ๊ธฐ๋ฐ˜
์ž‘์„ฑ์ž: ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž์šฉ ์š”์•ฝ ์ •๋ฆฌ


1๏ธโƒฃ ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘ (Entity Mapping)

JPA์—์„œ @Entity๋Š” ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ JPA๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ์ž„์„ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค.
DB ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

โœ”๏ธ ์ฃผ์š” ๋งคํ•‘ ์–ด๋…ธํ…Œ์ด์…˜

์–ด๋…ธํ…Œ์ด์…˜์„ค๋ช…
@Entity ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์—”ํ‹ฐํ‹ฐ์ž„์„ ์•Œ๋ฆผ
@Table(name = "ํ…Œ์ด๋ธ”๋ช…", uniqueConstraints = {...}) ํ…Œ์ด๋ธ” ์ด๋ฆ„ ๋ฐ ์œ ๋‹ˆํฌ ์ œ์•ฝ ์กฐ๊ฑด ์ง€์ •
@Column ์ผ๋ฐ˜ ์ปฌ๋Ÿผ ๋งคํ•‘
@Enumerated Enum ํƒ€์ž… ๋งคํ•‘
@Temporal Date ํƒ€์ž… ๋งคํ•‘ (์˜ˆ: @UpdateTimestamp๋กœ ์ž๋™ ์‹œ๊ฐ„ ์„ค์ • ๊ฐ€๋Šฅ)
@Lob CLOB, BLOB ํƒ€์ž… ๋งคํ•‘
@Entity
@Table(
    name = "member",
    uniqueConstraints = {
        @UniqueConstraint(columnNames = "email", name = "UK_MEMBER_EMAIL")
    }
)
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 50)
    private String name;
}




2๏ธโƒฃ ๊ธฐ๋ณธ ํ‚ค ๋งคํ•‘ (Primary Key Mapping)

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋งˆ๋‹ค ๊ธฐ๋ณธํ‚ค ์ƒ์„ฑ ๋ฐฉ์‹์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
์˜ˆ:

  • Oracle → ์‹œํ€€์Šค ๊ฐ์ฒด (SEQUENCE)
  • MySQL → AUTO_INCREMENT
    ์ด๋ฅผ ํ†ตํ•ฉ์ ์œผ๋กœ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด JPA๋Š” ๋‹ค์–‘ํ•œ ํ‚ค ์ƒ์„ฑ ์ „๋žต์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”น ์ง์ ‘ ํ• ๋‹น (Manual Assignment)

์—”ํ‹ฐํ‹ฐ๋ฅผ persist() ํ•˜๊ธฐ ์ „์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ง์ ‘ ๊ธฐ๋ณธํ‚ค๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

 
@Id private String id; // ์ง์ ‘ ์ง€์ •

๐Ÿ”น ์ž๋™ ์ƒ์„ฑ (Generated Value)

@Id์™€ @GeneratedValue๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ํ‚ค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

1. IDENTITY ์ „๋žต

  • DB์˜ ์ž๋™ ์ฆ๊ฐ€ ์ปฌ๋Ÿผ์— ์œ„์ž„ (MySQL, PostgreSQL ๋“ฑ)
  • ์ฆ‰, insert ์‹œ์ ์— DB๊ฐ€ ID๋ฅผ ์ƒ์„ฑํ•จ
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
 
 

2. SEQUENCE ์ „๋žต

  • DB ์‹œํ€€์Šค ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‚ค ์ƒ์„ฑ (Oracle, PostgreSQL ๋“ฑ)
  • ์‹œํ€€์Šค ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋ ค๋ฉด @SequenceGenerator ์‚ฌ์šฉ
@SequenceGenerator(
    name = "member_seq_gen",
    sequenceName = "member_seq",
    allocationSize = 1
)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "member_seq_gen")
private Long id;
 
 
 

3. TABLE ์ „๋žต

  • ๋ณ„๋„์˜ ํ‚ค ์ƒ์„ฑ ํ…Œ์ด๋ธ”์„ ์ด์šฉํ•ด ์‹œํ€€์Šค์ฒ˜๋Ÿผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹
  • DB ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘ ๊ฐ€๋Šฅ
 
@TableGenerator(
    name = "member_table_gen",
    table = "sequence_table",
    pkColumnValue = "member_seq",
    allocationSize = 1
)
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "member_table_gen")
private Long id;

 

4. AUTO ์ „๋žต

  • **DB ๋ฐฉ์–ธ(Dialect)**์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ์ ์ ˆํ•œ ์ „๋žต ์„ ํƒ
  • DB ๋ฒค๋”์— ์ข…์†๋˜์ง€ ์•Š์•„ ์ด์‹์„ฑ์ด ๋†’์Œ
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
 
 

โš™๏ธ ์ฐธ๊ณ  ์„ค์ •

Hibernate 5 ์ด์ƒ์—์„œ๋Š” hibernate.id.new_generator_mappings=true์„ค์ •์„ persistence.xml์ด๋‚˜ application.yml์— ์ถ”๊ฐ€ํ•ด์•ผ
์ƒˆ๋กœ์šด ํ‚ค ์ƒ์„ฑ ์ „๋žต์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.


3๏ธโƒฃ ์‹๋ณ„์ž(Primary Key) ์„ ํƒ ์ „๋žต

โœ… ๊ธฐ๋ณธ ํ‚ค์˜ ํ•„์ˆ˜ ์กฐ๊ฑด

  1. NULL ๊ฐ’์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
  2. ์œ ์ผํ•ด์•ผ ํ•œ๋‹ค.
  3. ๋ณ€ํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

๐ŸŒฟ ์ž์—ฐ ํ‚ค(Natural Key) vs ๋Œ€๋ฆฌ ํ‚ค(Surrogate Key)

๊ตฌ๋ถ„์„ค๋ช…์˜ˆ์‹œํŠน์ง•
์ž์—ฐ ํ‚ค ๋น„์ฆˆ๋‹ˆ์Šค ์˜๋ฏธ๊ฐ€ ์žˆ๋Š” ๊ฐ’ ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ, ์ด๋ฉ”์ผ, ์ „ํ™”๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ ์žˆ์Œ
๋Œ€๋ฆฌ ํ‚ค ๋น„์ฆˆ๋‹ˆ์Šค์™€ ๋ฌด๊ด€ํ•œ ์ž„์˜ ๊ฐ’ ์‹œํ€€์Šค, UUID ๋“ฑ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Œ, ๊ด€๋ฆฌ ์šฉ์ด

๊ถŒ์žฅ: ๋น„์ฆˆ๋‹ˆ์Šค์™€ ๋ฌด๊ด€ํ•œ ๋Œ€๋ฆฌ ํ‚ค(Surrogate Key) ์‚ฌ์šฉ
์ด์œ : ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ณ€ํ™”๋‚˜ ์ •์ฑ… ๋ณ€๊ฒฝ์—๋„ ์˜ํ–ฅ์ด ์ ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.


๐Ÿ ์ •๋ฆฌ

๊ตฌ๋ถ„์ „๋žตํŠน์ง•์ฃผ์š” DB
์ง์ ‘ ํ• ๋‹น @Id ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ง์ ‘ ์„ค์ • ๋ชจ๋“  DB
IDENTITY @GeneratedValue(strategy = IDENTITY) DB ์ž๋™ ์ฆ๊ฐ€ ์ปฌ๋Ÿผ ์‚ฌ์šฉ MySQL, PostgreSQL
SEQUENCE @GeneratedValue(strategy = SEQUENCE) ์‹œํ€€์Šค ๊ฐ์ฒด ์ด์šฉ Oracle, PostgreSQL
TABLE @GeneratedValue(strategy = TABLE) ํ‚ค ์ƒ์„ฑ์šฉ ํ…Œ์ด๋ธ” ์‚ฌ์šฉ ๋ชจ๋“  DB
AUTO @GeneratedValue(strategy = AUTO) ๋ฐฉ์–ธ์— ๋”ฐ๋ผ ์ž๋™ ์„ ํƒ ๋ชจ๋“  DB

๐Ÿ“˜ ์š”์•ฝ

  • ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘: @Entity, @Table, @Column, @Enumerated ๋“ฑ์„ ํ™œ์šฉ
  • ๊ธฐ๋ณธํ‚ค ์ƒ์„ฑ ์ „๋žต: IDENTITY, SEQUENCE, TABLE, AUTO
  • ์ถ”์ฒœ ์ „๋žต: ๋น„์ฆˆ๋‹ˆ์Šค์™€ ๋ฌด๊ด€ํ•œ ๋Œ€๋ฆฌ ํ‚ค ์‚ฌ์šฉ
  • ์„ค์ • ํŒ: Hibernate์˜ new_generator_mappings ์†์„ฑ ํ™œ์„ฑํ™” ํ•„์š”
๋ฐ˜์‘ํ˜•