๊ธฐ๋ณธ ํ‚ค ํ• ๋‹น ์ „๋žต

JPA๊ฐ€ ์ œ๊ณตํ•˜๋Š” DB ๊ธฐ๋ณธ ํ‚ค ํ• ๋‹น ์ „๋žต์€ ์ง์ ‘ ํ• ๋‹น ๋ฐฉ์‹, ์ž๋™ ์ƒ์„ฑ ๋ฐฉ์‹ ๋‘ ๊ฐ€์ง€์ด๋‹ค.

์ด ์ค‘ ์ง์ ‘ ํ• ๋‹น ๋ฐฉ์‹์€ Application์—์„œ ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์ง์ ‘ ํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

์ž๋™ ์ƒ์„ฑ ๋ฐฉ์‹์€ ๋Œ€๋ฆฌ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ IDENTITY, SEQUENCE, TABLE ๋„ค ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

ํ•ด๋‹น ๋ฐฉ์‹๋“ค์€ ์‚ฌ์šฉํ•˜๋Š” DB์— ์˜์กดํ•œ๋‹ค.
MySQL์€ IDENTITY ์‚ฌ์šฉ, Oracle์€ SEQUENCE ์‚ฌ์šฉ


์ง์ ‘ ํ• ๋‹น ๋ฐฉ์‹

์ง์ ‘ ํ• ๋‹น ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ Entity๋ฅผ ์ƒ์„ฑํ•  ๋•Œ Key Column์— @Id๋งŒ ์‚ฌ์šฉํ•ด ์ฃผ์–ด๋„ ๋œ๋‹ค.

@Id
private long id;

@Id๊ฐ€ ์ ์šฉ ๊ฐ€๋Šฅํ•œ Java Type์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • Java ๊ธฐ๋ณธํ˜•(int, double, long ...)
  • Java Wrapper ํ˜•
  • String
  • java.util.Date
  • java.sql.Date
  • java.math.BigDecimal
  • java.math.BigInteger

ํ•ด๋‹น ์ „๋žต์€ em.persist()๋กœ Entity๋ฅผ ์ €์žฅ ํ•˜๊ธฐ ์ „,

Application์—์„œ ์ง์ ‘ ๊ธฐ๋ณธ ํ‚ค๋ฅผ ํ• ๋‹นํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");

EntityManager em = emf.createEntityManager();

User user = new User();
user.setName("gillog");
user.setId(1);

em.persist(user);

์ž๋™ ์ƒ์„ฑ ๋ฐฉ์‹

์ž๋™ ์ƒ์„ฑ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ @Id์™€ @GeneratedValue๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

IDENTITY

๊ธฐ๋ณธ ํ‚ค ์ƒ์„ฑ์„ DB์— ์œ„์ž„ํ•˜๋Š” ์ „๋žต์ด๋‹ค.

MySQL๊ณผ ๊ฐ™์ด Sequence๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๊ณ , AutoIncrement ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด,

๊ธฐ๋ณธ ํ‚ค ๊ฐ’์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” DBMS์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

์ฃผ๋กœ MySQL, PostgreSQL, SQL Server, DB2์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋‹ค.

@Id
@GeneratedValue=strategy = GenerationType.IDENTITY)
private long id;

IDENTITY์ „๋žต์€ Data๋ฅผ DB์— Insertํ•œ ํ›„ ๊ธฐ๋ณธ ํ‚ค ๊ฐ’์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

Entity์— ์‹๋ณ„์ž ๊ฐ’์„ ํ• ๋‹นํ•˜๋ ค๋ฉด JPA๋Š” ์ถ”๊ฐ€๋กœ DB๋ฅผ ์กฐํšŒํ•ด์•ผ ํ•˜๋Š”๋ฐ,

Hibernate๋Š” JDBC3์— ์ถ”๊ฐ€๋œ Statement.getGeneratedKeys()๋ฅผ ์‚ฌ์šฉํ•ด DB์™€ ํ•œ๋ฒˆ๋งŒ ํ†ต์‹ ํ•œ๋‹ค.
ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋Š” Data๋ฅผ ์ €์žฅํ•˜๋ฉด์„œ, ์ƒ์„ฑ๋œ ๊ธฐ๋ณธ ํ‚ค ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค.

ํ•˜์ง€๋งŒ Entity๊ฐ€ ์˜์† ์ƒํƒœ๊ฐ€ ๋˜๋ ค๋ฉด ์‹๋ณ„์ž๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ๋ฐ,

DB์— ์ €์žฅํ•ด์•ผ๋งŒ ์‹๋ณ„์ž๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์ด๋ฏ€๋กœ,

em.persist()ํ˜ธ์ถœ ์ฆ‰์‹œ Insert Query๋ฅผ DB์— ์ „๋‹ฌํ•ด ์‹๋ณ„์ž๋ฅผ ๊ฐ€์ ธ์˜ค๋ฏ€๋กœ,

Transaction์„ ์ง€์›ํ•˜๋Š” ์“ฐ๊ธฐ ์ง€์—ฐ ๋ฐฉ์‹์ด ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.

SEQUENCE

ํ•ด๋‹น ๋ฐฉ์‹์€ DB Sequence๋ฅผ ์‚ฌ์šฉํ•ด ๊ธฐ๋ณธ ํ‚ค๋ฅผ ํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ,

Sequence ์ „๋žต์„ ์ง€์›ํ•˜๋Š” Oracle, PostgreSQL, DB2, H2 DB์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด DB์—์„œ Seqeunce๋ฅผ ์ƒ์„ฑ ํ›„์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

CREATE SEQUENCE USER_SEQ START WITH 1 INCREMENT BY 1;

ํ›„์— Entity๋ฅผ ์ƒ์„ฑํ•  ๋•Œ @SequenceGenerator Annotation์„ ์‚ฌ์šฉํ•œ๋‹ค.

@Entity
@SequenceGenerator(
    name = "USER_SEQ_GENERATOR"
    , sequenceName = "USER_SEQ"
    , initialValue = 1
    , allocationSize = 1
)
public class User {

    @Id
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE
        , generator = "USER_SEQ_GENERATOR"
    )
    private long id;

}

@SequenceGenerator Annotation์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์†์„ฑ๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

์†์„ฑ ์„ค๋ช… ๊ธฐ๋ณธ ๊ฐ’
name ์‹๋ณ„์ž ์ƒ์„ฑ๊ธฐ ์ด๋ฆ„ ์—†์Œ ์ง€์ • ํ•„์ˆ˜.
sequenceName DB์— ๋“ฑ๋ก๋˜์–ด ์žˆ๋Š” Sequence์ด๋ฆ„ hibernate_sequence
initalValue(DDL) DDL ์ƒ์„ฑ์‹œ์—๋งŒ ์‚ฌ์šฉ, Sequence DDL ์ƒ์„ฑ์‹œ ์ฒ˜์Œ ์‹œ์ž‘ value๋ฅผ ์„ค์ • 1
allocationSize Sequence ํ•œ๋ฒˆ ํ˜ธ์ถœ์‹œ ์ฆ๊ฐ€ํ•˜๋Š” ์ˆ˜(์„ฑ๋Šฅ ์ตœ์ ํ™”์— ์‚ฌ์šฉ) 50
catalog, schema DB catalog, schema ์ด๋ฆ„  

allocationSize์™€ ์„ฑ๋Šฅ ์ตœ์ ํ™”

allocationSize๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์ด 50์ด๋ฏ€๋กœ ํ•ด๋‹น ์†์„ฑ์„ 1๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์„ ์‹œ,

sequence ํ˜ธ์ถœ ์‹œ๋งˆ๋‹ค 50์”ฉ ์ฆ๊ฐ€ํ•œ๋‹ค.

๊ธฐ๋ณธ ๊ฐ’์ด 50์ธ ์ด์œ ๋Š” JPA๊ฐ€ sequence์— ์ ‘๊ทผ ํšŸ์ˆ˜๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•จ์ด๋‹ค.

allocationSize์— ์„ค์ • ๊ฐ’ ๋งŒํผ ํ•œ ๋ฒˆ์— sequence๋ฅผ ์ฆ๊ฐ€ ์‹œํ‚ค๊ณ , ๊ทธ๋งŒํผ Memory์— seqeunce ๊ฐ’์„ ํ• ๋‹นํ•œ๋‹ค.

๊ทธ ํ›„ Memory๋ฅผ ํ™œ์šฉํ•ด JVM์•ˆ์—์„œ sequence๋ฅผ ํ• ๋‹น ํ•œ๋‹ค.

์ด ๋ฐฉ๋ฒ•์€ sequenc๋ฅผ ์„ ์ ํ•˜์—ฌ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ JVM์ด ๋™์‹œ ๋™์ž‘ํ•ด๋„ ๊ธฐ๋ณธ ํ‚ค ๊ฐ’์ด ์ถฉ๋Œํ•˜์ง€ ์•Š๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

IDENTITY VS SEQUENCE

IDENTITY ์ „๋žต์€ ๋จผ์ € Entity๋ฅผ DB์— ์ €์žฅํ•œ ํ›„์—,

์‹๋ณ„์ž๋ฅผ ์กฐํšŒํ•ด Entity์˜ ์‹๋ณ„์ž๋กœ ํ• ๋‹นํ•˜๋Š” ์ „๋žต์ด๋‹ค.

SEQUENCE ์ „๋žต์€ em.persist() ํ˜ธ์ถœ ์ „์— ๋จผ์ € DB Sequence๋ฅผ ๋จผ์ € ์กฐํšŒํ•œ๋‹ค.

๊ทธ ํ›„ ์กฐํšŒํ•œ ์‹๋ณ„์ž๋ฅผ Entity์— ํ• ๋‹นํ•œ ํ›„ Entity๋ฅผ ์˜์†์ƒํƒœ๋กœ ์ €์žฅํ•œ๋‹ค.

๊ทธ ํ›„ Transaction์„ Commitํ•˜์—ฌ Flush๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ ํ•ด๋‹น Entity๋ฅผ DB์— ์ €์žฅํ•œ๋‹ค.

TABLE

ํ•ด๋‹น ์ „๋žต์€ Key ์ƒ์„ฑ Table์„ ์‚ฌ์šฉํ•˜๋Š” ์ „๋žต์ด๋‹ค.

Key ์ƒ์„ฑ ์ „์šฉ Table์„ ์ƒ์„ฑํ•˜๊ณ , name, value๋กœ ์‚ฌ์šฉํ•  Column์„ ์ƒ์„ฑํ•˜์—ฌ

DB Sequence๋ฅผ ํ‰๋‚ด๋‚ด๋Š” ์ „๋žต์ด๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด Key ์ƒ์„ฑ ์ „์šฉ Table์„ ์ƒ์„ฑํ•œ ํ›„,

CREATE TABLE CUSTOM_SEQUENCE {
    sequence_name varchar(255) not null
    , next_val bigint
    , primary key (sequence_name)
}

@TableGenerator Annotation์„ ์‚ฌ์šฉํ•ด Entity๋ฅผ Mappingํ•œ๋‹ค.

@Entity
@TableGenerator(
    name = "USER_SEQ_GENERATOR"
    , table = "CUSTOM_SEQUENCE"
    , pkColumnValue = "USER_SEQ"
    , allocationSize = 1
)
public class User {

    @Id
    @GeneratedValue(
        strategy = GenerationType.TABLE
        , generator = "USER_SEQ_GENERATOR"
    )
    private long id;

}

ํ•ด๋‹น ์ „๋žต์€ SEQUENCE ์ „๋žต๊ณผ ๋‚ด๋ถ€ ๋™์ž‘ ๋ฐฉ์‹์ด ๊ฐ™๋‹ค.

pkColumnValue๋กœ ์„ค์ •ํ•œ USER_SEQ๋ผ๋Š” SEQUENCE NAME์„ CUSTOM_SEQUENCE Table์˜ sequence_name Column์— ์ƒ์„ฑํ•œ ํ›„,
next_val Column์˜ ๊ฐ’์ด ์ฆ๊ฐ€ํ•œ๋‹ค.
๊ฐ’์ด ์—†์œผ๋ฉด JPA๊ฐ€ Insertํ•˜๋ฉด์„œ ์ดˆ๊ธฐํ™”ํ•˜๋ฏ€๋กœ ๋ฏธ๋ฆฌ ๊ฐ’์„ ๋„ฃ์–ด๋‘์ง€ ์•Š์•„๋„ ๋จ

@TableGenerator์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์†์„ฑ๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

์†์„ฑ ์„ค๋ช… ๊ธฐ๋ณธ ๊ฐ’
name ์‹๋ณ„์ž ์ƒ์„ฑ๊ธฐ ์ด๋ฆ„ ์—†์Œ ์ง€์ • ํ•„์ˆ˜.
table ํ‚ค ์ƒ์„ฑ ํ…Œ์ด๋ธ” ๋ช… hibernate_sequences
pkColumnName ์‹œํ€€์Šค ์ปฌ๋Ÿผ ๋ช… sequence_name
valueColumnName ์‹œํ€€์Šค ๊ฐ’ ์ปฌ๋Ÿผ ๋ช… next_val
pkColumnValue ํ‚ค๋กœ ์‚ฌ์šฉํ•  ๊ฐ’ ์ด๋ฆ„ Entity ์ด๋ฆ„
initialValue ์ดˆ๊ธฐ ๊ฐ’, ๋งˆ์ง€๋ง‰ ์ƒ์„ฑ๋œ ๊ฐ’์ด ๊ธฐ์ค€ 0
allocationSzie ์‹œํ€€์Šค ํ˜ธ์ถœ์‹œ ์ฆ๊ฐ€ ๊ฐ’(์„ฑ๋Šฅ ์ตœ์ ํ™”์— ์‚ฌ์šฉ) 50
catalog, schema DB catalog, schema ์ด๋ฆ„  
uniqueConstraints(DDL) ์œ ๋‹ˆํฌ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ง€์ •  

 

 

TABLE ์ „๋žต์€ ๊ฐ’์„ ์กฐํšŒํ•˜๋ฉด์„œ Select Query๋ฅผ, ๊ทธ ํ›„ ๊ฐ’ ์ฆ๊ฐ€๋ฅผ ์œ„ํ•ด Update Query๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

SEQUENCE ์ „๋žต๊ณผ ๋น„๊ตํ•ด DB์™€ ํ•œ๋ฒˆ ๋” ํ†ต์‹ ํ•˜๋Š” ๋‹จ์ ์ด ์žˆ๊ณ ,

SEQUENCE ์ „๋žต์˜ ์ตœ์ ํ™”์™€ ๊ฐ™์ด allocationSize๋ฅผ ์‚ฌ์šฉํ•ด ์ตœ์ ํ™” ํ•œ๋‹ค.

AUTO

AUTO ์ „๋žต์€ ์„ ํƒํ•œ DB ๋ฐฉ์–ธ์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ IDENTITY, SEQUENCE, TABLE ์ „๋žต์„ ์ž๋™์œผ๋กœ ์„ ํƒํ•œ๋‹ค.
DB์˜ ์ข…๋ฅ˜๋„ ๋งŽ๊ณ , ๊ธฐ๋ณธ ํ‚ค ์ƒ์„ฑ ๋ฐฉ์‹๋„ ๋‹ค์–‘ํ•˜๊ธฐ์—

ํ•ด๋‹น ์ „๋žต์€ DB๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ Code ์ˆ˜์ •์„ ํ•˜์ง€ ์•Š์•„๋„ ๋˜๋Š” ์žฅ์ ๊ณผ,

Key ์ƒ์„ฑ ์ „๋žต์ด ์ •ํ•ด์ง€์ง€ ์•Š์€ ๊ฐœ๋ฐœ ์ดˆ๊ธฐ ๋‹จ๊ณ„๋‚˜ ํ”„๋กœํ† ํƒ€์ž… ๊ฐœ๋ฐœ ์‹œ์— ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋งŒ์•ฝ AUTO๋กœ SEQUENCE๋‚˜ TABLE์ „๋žต์ด ์„ ํƒ ๋  ๊ฒฝ์šฐ,

Sequence๋‚˜ ํ‚ค ์ƒ์„ฑ Table์„ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด ๋‘์–ด์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ DDL ์ž๋™ ์ƒ์„ฑ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, Hibernate๊ฐ€ ๊ธฐ๋ณธ ๊ฐ’์„ ์‚ฌ์šฉํ•ด ์•Œ์•„์„œ ์ƒ์„ฑํ•ด์ค€๋‹ค.