๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ/JPA - Hibernate

01. ์•Œ์•„๋‘๋ฉด ์“ธ๋–ผ์žˆ๋Š” GeneratedValue ์ด์•ผ๊ธฐ Part1

by YangsDev 2020. 6. 4.

์˜ค๋Š˜์˜ ๊ธ€์˜ ์‹œ์ž‘

์‹œ์ž‘ํ•˜๋ฉฐ

์šฐ๋ฆฌ๋Š” Entity๋ฅผ ๋งŒ๋“ค ๋•Œ ์šฐ๋ฆฌ๋Š” PK (Primary Key)๋ฅผ ์ง€์ •ํ•œ๋‹ค.

๊ทธ์ค‘์—์„œ๋„ Primary Key๋ฅผ ์„ ํƒํ•  ๋•Œ, ์ „๋žต์ ์œผ๋กœ ์ƒ๊ฐํ–ˆ์„ ๋•Œ ์ˆœ์ฐจ ์ฆ๊ฐ€ ๊ฐ’์„ ํฌ๊ธฐํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.

๊ณผ์—ฐ ๊ทธ๋Ÿผ JPA์—์„œ๋Š” ์ด๋Ÿฐ ๋Œ€์ฒด ํ‚ค๋ฅผ ์–ด๋–ป๊ฒŒ ์ƒ์„ฑํ•˜๊ณ , ์–ด๋–ค์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž.

 

GeneratedValue๋ž€?

import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;

@Table(name = "coupon")
@Entity
@Getter
@Setter
public class Coupon implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "coupon_id", insertable = false, nullable = false)
    private Long couponId;

    @Column(name = "coupon", nullable = false, unique = true)
    private String coupon;

    @Column(name = "coupon_status", nullable = false)
    private CouponStatus status;

    @Column(name = "reg_timestamp", nullable = false)
    private LocalDateTime regTimestamp;

    @Column(name = "expired_timestamp", nullable = false)
    private LocalDateTime expiredTimestamp;
}

JPA๋Š” ์ด๋Ÿฌํ•œ ๊ธฐ๋ณธํ‚ค๋ฅผ ์ž๋™์ƒ์„ฑ ํ•˜๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•ด '@Id'์™€ '@GeneratedValue' ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์ œ๊ณต์„ ํ•œ๋‹ค.

์—ฌ๊ธฐ์—” ์ž๋™ ์ƒ์‚ฐ ์ „๋žต์„ 4๊ฐ€์ง€๋กœ ์ œ๊ณต ํ•˜๊ฒŒ ๋œ๋‹ค.

๋ชจ๋“œ ์„ค๋ช…
Auto (Default) JPA๊ฐ€ ์•Œ์•„์„œ ํ•˜๊ฒ ์Œ
IDENTITY ๊ธฐ๋ณธํ‚ค ์ƒ์„ฑ์„ DB์—๊ฒŒ ์œ„์ž„
SEQUENCE DB์—์„œ `SEQUENCE`๋ฅผ ์ง€์›ํ•œ๋‹ค๋ฉด, ์‚ฌ์šฉ ์•„๋‹ˆ๋ผ๋ฉด Table Mode
TABLE DB์— ํ‚ค์šฉ ํ…Œ์ด๋ธ”์ด ์ƒ๊น€ (hibernate_sequence)

GeneratedType.AUTO ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹

AUTO (Default)๋กœ ์‚ฌ์šฉ ํ•˜๋ฉด ์œ„ ์ˆœ์„œ๋„ ๋Œ€๋กœ ์‹œ์Šคํ…œ์ด ๋™์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

1. UUID๋ผ๋ฉด, UUID๋กœ ์ฒ˜๋ฆฌ ํ•œ๋‹ค.

2. UUID๊ฐ€ ์•„๋‹ˆ๊ณ  Number Data Type์ด๋ผ๋ฉด `hibernate.id.new_generator_mapping`์˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ฒŒ ๋œ๋‹ค.

2-1. FALSE๋ผ๋ฉด, Native Genertaor๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค (MySQL์ด๋ผ๋ฉด `auto_increment`)

3. hibernate.id.new_generator_mapping ์ด TRUE ๋ผ๋ฉด `SequenceStyleGenetrator` ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

3-1. Sequence Call์„ ํ•˜๊ฒŒ ๋˜๊ณ ,  ID๋ฅผ ๋ฐ›๋Š”๋‹ค

3-2. ๋งŒ์•ฝ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋Š” DBMS๊ฐ€ Sequence API๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด `GeneratedType.TABLE`๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

 

 

GeneratedType.IDENTITY ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹

์ด ๋ฐฉ์‹์€ ID ์ƒ์„ฑ์— ๋Œ€ํ•ด DB์— ๋ชจ๋“  ๊ฒƒ์„ ์œ„์ž„์‹œํ‚ค๋Š” ํ˜•ํƒœ์ด๋‹ค.

์‹ค์ œ ์ž…๋ ฅ ๋‹จ๊ณ„์—์„œ๋Š” NULL๋กœ ์„ค์ •๋˜์–ด, DB์— ๋„˜์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.

๊ฒฐ๋ก ์ ์œผ๋กœID๋ฅผ JPA์—์„œ ์ฑ„์›Œ์„œ ๋„ฃ์ง€๋Š” ์•Š๋Š”๋‹ค.

ํ•˜์ง€๋งŒ, ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ์œ ์ง€ ํ•˜๊ธฐ ์œ„ํ•˜์—ฌ, ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๋ช‡๋ฒˆ ID๋กœ ์ €์žฅ ํ•˜์˜€๋Š”์ง€ ๋ฐ›์•„์˜ค๊ฒŒ ๋œ๋‹ค.

 

GeneratedType.IDENTITY์—์„œ์˜ BULK INSERT?

์ตœ๊ทผ์— JPA (Hibernate ๊ตฌํ˜„์ฒด)๋ฅผ BULK INSERT๋ฅผ ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์—ˆ๋‹ค.

์„ฑ๋Šฅ์ด ๋„ˆ๋ฌด ์•ˆ๋‚˜์˜ค๊ธธ๋ž˜, SQL ์ฟผ๋ฆฌ๋ฅผ ์ฐ์–ด๋ณด๋‹ˆ ๊ทธ๋ƒฅ ๊ทธ๋Œ€๋กœ ๋‚ ์•„๊ฐ€๊ณ  ์žˆ์—ˆ๋‹ค.

 

ํ•˜์ด๋ฒ„๋„ค์ดํŠธ ๊ณต์‹ ๋ฌธ์„œ์—์„œ ๊ทธ ์ด์œ ๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

 

Hibernate ORM 5.4.17.Final User Guide

Fetching, essentially, is the process of grabbing data from the database and making it available to the application. Tuning how an application does fetching is one of the biggest factors in determining how an application will perform. Fetching too much dat

docs.jboss.org

๋ธ”๋กœ๊ทธ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ๋‚˜์˜ค๋Š” ์งค ์ค‘ ํ•˜๋‚˜์ธ๋“ฏ..

Hibernate disables insert batching at the JDBC level transparently if you use an identity identifier generator.

'IDENTITY'๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅ ํ•  ๊ฒฝ์šฐ JDBC ๋ ˆ๋ฒจ์—์„œ batch insert๋ฅผ ๋น„ํ™œ์„ฑํ™” ํ•œ๋‹ค๋Š” ๊ฒƒ ์ด๋‹ค.

 

๊ทผ๋ฐ ์™œ ๊ทธ๋žฌ๋Š”์ง€์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋Š” ๊ณต์‹ ๋ฌธ์„œ์— ์—†๊ธธ๋ž˜, ๋‹ค๋ฅธ ๋ธ”๋กœ๊ทธ์— ์žˆ๋Š” StackOverflow๊ธ€์„ ๊ฐ€์ ธ์™”๋‹ค.

https://stackoverflow.com/questions/27697810/hibernate-disabled-insert-batching-when-using-an-identity-identifier-generator/27732138#27732138

 

Hibernate disabled insert batching when using an identity identifier generator

The Hibernate documentation says: Hibernate disables insert batching at the JDBC level transparently if you use an identity identifier generator. But all my entities have this configuration:...

stackoverflow.com

 

The only drawback is that we can’t know the newly assigned value prior to executing the INSERT statement. This restriction is hindering the “transactional write behind” flushing strategy adopted by Hibernate. For this reason, Hibernates disables the JDBC batch support for entities using the IDENTITY generator.

ํ•œ์ค„์š”์•ฝ : hibernate์˜ 'transactional write behind'์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์–ด์„œ ๋‹ˆ๋„ค๊ฐ€ ์•„๋ฌด๋ฆฌ ์š”์ฒญํ•ด๋„ ๋‚ด๊ฐ€ ๊บผ๋ฒ„๋ฆด๊บผ์•ผ..

 

 

 

GeneratedType.IDENTITY ์ƒํƒœ์—์„œ Batch Insert๋Š”?

??????????????????????

SEQUENCE ์“ฐ์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„(?) ์ด ๋‹ต์ด ๋ผ๊ณ  ์ด์•ผ๊ธฐ ํ•˜๋ฉด ์ด๊ฑด ๋ฌด์ฑ…์ž„ ํ•œ ์ด์•ผ๊ธฐ ์ด๊ณ , ๋งŒ์•ฝ ๋’ค์— ์—ฐ๊ฒฐ๋˜๋Š” DB๊ฐ€ MYSQL์ด๋ผ๋ฉด ์•„๋ž˜์˜ ๊ธ€์„ ๊ผญ ๋ณด๊ธธ ๋ฐ”๋ž€๋‹ค.

 

HomoEfficio/dev-tips

๊ฐœ๋ฐœํ•˜๋‹ค ๋งˆ์ฃผ์ณค๋˜ ์ž‘์€ ๋ฌธ์ œ๋“ค๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ์ •๋ฆฌ. Contribute to HomoEfficio/dev-tips development by creating an account on GitHub.

github.com

ํ•œ์ค„์š”์•ฝ์งค

MYSQL์—์„œ๋Š” `SEQUENCE`API๊ฐ€ ์—†๋‹ค.. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— Hibernate๋Š” Tableํ˜•ํƒœ๋กœ ์ง„ํ–‰ํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ ๊ทธ๋Ÿผ ์œ„์™€ ๊ฐ™์€ ์žฌ์•™์ด ์ผ์–ด๋‚˜๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค. (๋ง์ž‡๋ชป..)

 

์•”ํŠผ ๋ณธ๋ก ์œผ๋กœ ๋Œ์•„์™€์„œ, ์•„๊นŒ ๊ทธ Stackoverflow ๊ธ€์— ์ด์•ผ๊ธฐ๋ฅผ ๋‹ค์‹œํ•ด๋ณด์ž.

Therefore, using IDENTITY is still the best choice on MySQL, and if you need batching for insert, 
you can use jOOQ for that. Hibernate and jOOQ are a great combo.

๊ฒฐ๋ก ์€ Hibernate๋งŒ ์‚ฌ์šฉํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๊ธด ์–ด๋ ค์šฐ๋‹ˆ jooq๋ฅผ ๊ฐ™์ด ์‚ฌ์šฉ ํ•ด๋ผ. ๋‘˜์€ ์ตœ๊ณ ์˜ ์กฐํ•ฉ์ด๋‹ค. ๋ผ๊ณ  ์ด์•ผ๊ธฐ ํ•œ๋‹ค.

๊ฒฐ๊ตญ ๋‚˜ ์—ญ์‹œ JOOQ๋กœ ๊ตฌํ˜„ ํ–ˆ๋Š”๋ฐ, ์งœ์ฆ๋‚˜๋Š”์ผ์ด ๊ฝค ์žˆ์—ˆ๋‹ค.

 

์ด ๋ถ€๋ถ„์€ ๋‹ค๋ฅธ ์‹œ๋ฆฌ์ฆˆ์—์„œ ๋‹ค๋ค„๋ณด๊ธฐ๋กœ ํ•œ๋‹ค.

 

 

Part2์—์„œ๋Š”?

์›๋ž˜๋Š” ํ•˜๋‚˜์˜ ๊ธ€์—์„œ ์ด์•ผ๊ธฐ๋ฅผ ๋‹ค ํ’€์–ด๋ณด๋ ค๊ณ  ํ•˜์˜€์œผ๋‚˜, ์ƒ๊ฐ ๋ณด๋‹ค ๊ธ€์ด ๊ธธ์–ด์ง€๊ธฐ๋„ ํ•˜์˜€๋‹ค.

๊ทธ๋ฆฌ๊ณ  `GeneratedType.SEQUENCE`์— ๋Œ€ํ•ด์„œ๋Š” ๊ฝค ๊ธด ์ด์•ผ๊ธฐ๊ฐ€ ์žˆ์„๋“ฏ ํ•˜์—ฌ ๋‚˜๋ˆ ์„œ ์ด์•ผ๊ธฐ ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

 

Part2์—์„œ๋Š” 'GeneratedType.SEQUENCE', 'GeneratedType.TABLE' ๊ทธ๋ฆฌ๊ณ  ๊ฒฐ๋ก ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐ ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

 

 

๋Œ“๊ธ€