본문 바로가기
개발/JPA

[JPA] @GeneratedValue 사용하기

by 코딩하는 흰둥이 2024. 11. 14.
TEST 테이블
-- Oracle 
CREATE TABLE BOARD(
	NO		NUMBER PRIMARY KEY,
	TITLE		VARCHAR2(50),
	WRITER		VARCHAR2(20),
	CONTENTS 	CLOB,
	CREATED		DATE DEFAULT SYSDATE 
)


-- Ms sql
CREATE TABLE BOARD(
	NO		BIGINT IDENTITY PRIMARY KEY,
	TITLE		VARCHAR(50),
	WRITER		VARCHAR(20),
	CONTENTS 	VARCHAR(MAX),
	CREATED		DATE DEFAULT GETDATE() 
)

 

 

 

Controller
@RestController
@RequestMapping("/api/*")
public class BoardController {

    @Autowired
    private BoardRepository boardRepository;
    
    @PostMapping("/boardSave")
    public String boardSave(@RequestBody Board vo, @RequestParam String checkToken) throws Exception{

        try {
            // refreshToken 에서 사용자의 username 을 가져온다
            String username = jwtTokenUtil.getUsernameFromRefreshToken(checkToken);
            vo.setWriter(username);
            
            boardRepository.save(vo);
            
            return "success";
        }catch (Exception e){
            e.printStackTrace();
            return "유효하지 않은 사용자";
        }
    }
}

 

 

 

 

 

 

 

GenerationType.IDENTITY
@Data
@Entity                         // JPA 의 Entity class 라고 지정
@Table(name = "Board")          // DB 테이블 지정
public class Board {

    // Primary Key 인 기본 키를 지정한다
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)     // pk 값이 자동으로 증가된다
    private Long no;

    // Table의 컬럼과 매핑시킨다 , nullable 로 null 허용을 설정 한다 , default = true 다
    @Column(nullable = false)
    private String title;

    // length 로 문자열 길이를 설정한다
    @Column(nullable = false)
    private String writer;

    @Lob
    private String contents;

    @Column(nullable = false)
    private LocalDateTime created;

    @PrePersist
    public void prePersist() {
        if (this.created == null) {
            this.created = LocalDateTime.now(); // 현재 시간으로 설정
        }
    }
}

 

GenerationType.IDENTITY 설정을 사용하려면

Table 의 컬럼에 Identity 설정이 되어 있어야 한다

Ms sql 로 진행하였다

 

 

 

IDENTITY  로 설정한 NO 를 제외하고 insert 한다

 

 

 

 

 

 

GenerationType.SEQUENCE
CREATE SEQUENCE board_seq	-- 시퀀스명
       INCREMENT BY 1		-- 증가값
       START WITH 1		-- 시작값
       MINVALUE 1		-- 최솟값
       MAXVALUE 9999		-- 최댓값
       NOCYCLE			-- 최댓값 도달하면 다시 반복안함 , CYCLE(반복함)
       NOCACHE			-- Cache 사용 여부 , CACHE(사용함)
       NOORDER			-- 요청 순서대로 값을 생성 여부 , ORDER(순서대로 생성)

Oracle 시퀀스 생성

 

-- 시퀀스 삭제
DROP SEQUENCE board_seq;
       
-- 시퀀스 현재 값 확인
SELECT board_seq.CURRVAL FROM dual;
      
-- 시퀀스 다음 값
SELECT board_seq.NEXTVAL FROM dual;

시퀀스 명령어

 

 

 

@Data
@Entity                         // JPA 의 Entity class 라고 지정
@Table(name = "Board")          // DB 테이블 지정
public class Board {

    // Primary Key 인 기본 키를 지정한다
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "board_seq_jpa")     // 시퀀스를 사용하여 기본 키를 생성한다
    @SequenceGenerator(
            name = "board_seq_jpa",         // Entity 에서 사용할 시퀀스명
            sequenceName = "board_seq",     // DB 에서 생성한 시퀀스 명
            allocationSize = 1              // 한번에 할당하는 값
    )
    private Long no;

    // Table의 컬럼과 매핑시킨다 , nullable 로 null 허용을 설정 한다 , default = true 다
    @Column(nullable = false)
    private String title;

    // length 로 문자열 길이를 설정한다
    @Column(nullable = false)
    private String writer;

    @Lob
    private String contents;

    @Column(nullable = false)
    private LocalDateTime created;

    @PrePersist
    public void prePersist() {
        if (this.created == null) {
            this.created = LocalDateTime.now(); // 현재 시간으로 설정
        }
    }
}

 

 

 

저장 테스트

 

 

 

다음 시퀀스 값을 조회하고 insert를 하고 있다

 

 

자동 생성되어 insert

 

 

 

GenerationType.TABLE
-- Oracle     
CREATE TABLE TABLE_KEY (
    KEY_NAME 				VARCHAR(255) NOT NULL,
    NEXT_VAL				NUMBER,
    PRIMARY KEY (KEY_NAME)
);

Oracle - Key 를 담을 Table 을 생성한다

 

 

@Data
@Entity                         // JPA 의 Entity class 라고 지정
@Table(name = "Board")          // DB 테이블 지정
public class Board {

    // Primary Key 인 기본 키를 지정한다
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE , generator = "board_key")        // 테이블을 이용하여 키를 생성한다
    @TableGenerator(
            name = "board_key",             // Entity 에서 사용할 Key Table 명
            table = "TABLE_KEY",            // DB 에서 생성한 키를 담을 Table 명
            pkColumnName = "KEY_NAME",      // 기본 키로 사용할 컬럼 명
            valueColumnName = "NEXT_VAL",   // key 를 저장할 컬럼 명
            pkColumnValue = "board_seq",    // key_name 컬럼에 저장 될 Entity 에 대한 key 구분 값
            initialValue = 1,               // 초기 값
            allocationSize = 1              // 키 증가 값
    )
    private Long no;

    // Table의 컬럼과 매핑시킨다 , nullable 로 null 허용을 설정 한다 , default = true 다
    @Column(nullable = false)
    private String title;

    // length 로 문자열 길이를 설정한다
    @Column(nullable = false)
    private String writer;

    @Lob
    private String contents;

    @Column(nullable = false)
    private LocalDateTime created;

    @PrePersist
    public void prePersist() {
        if (this.created == null) {
            this.created = LocalDateTime.now(); // 현재 시간으로 설정
        }
    }
}

 

GenerationType.TABLE 은 테이블을 이용하여 키를 생성하는 방식이다

 

 

@Data
@Entity                         // JPA 의 Entity class 라고 지정
@Table(name = "Board")          // DB 테이블 지정
public class Board {

    // Primary Key 인 기본 키를 지정한다
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE , generator = "board_key")        // 테이블을 이용하여 키를 생성한다
    @TableGenerator(
            name = "board_key",             // Entity 에서 사용할 Key Table 명
            table = "table_key",            // DB 에서 생성한 키를 담을 Table 명
            pkColumnName = "key_name",      // 기본 키로 사용할 컬럼 명
            valueColumnName = "next_val",   // key 를 저장할 컬럼 명
            pkColumnValue = "board_seq",    // key_name 컬럼에 저장 될 Entity 에 대한 key 구분 값
            initialValue = 1,               // 초기 값
            allocationSize = 1              // 키 증가 값
    )
    private Long no;

    // Table의 컬럼과 매핑시킨다 , nullable 로 null 허용을 설정 한다 , default = true 다
    @Column(nullable = false)
    private String title;

    // length 로 문자열 길이를 설정한다
    @Column(nullable = false)
    private String writer;

    @Lob
    private String contents;

    @Column(nullable = false)
    private LocalDateTime created;

    @PrePersist
    public void prePersist() {
        if (this.created == null) {
            this.created = LocalDateTime.now(); // 현재 시간으로 설정
        }
    }
}

 

 

 

 

저장 테스트

 

 

 

 

Key Table 에서 Key 값을 Select 하고

증가 값을 Update 한 뒤에 증가된 값으로 Insert 를 진행하고 있다

 

 

 

Update 한 증가값으로 Insert

 

 

 

@TableGenerator 에서 설정한

pkColumnValue = "board_seq" 으로 DB 에 저장된 것을 볼 수 있다

GenerationType.TABLE 을 이용하면 각각 시퀀스를 생성하여 증가값을 불러오지 않아도

Table 하나로 관리할 수 있다

 

GenerationType.AUTO
@Data
@Entity                         // JPA 의 Entity class 라고 지정
@Table(name = "Board")          // DB 테이블 지정
public class Board {

    // Primary Key 인 기본 키를 지정한다
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)         // JPA 에서 자동으로 키를 생성한다
    private Long no;

    // Table의 컬럼과 매핑시킨다 , nullable 로 null 허용을 설정 한다 , default = true 다
    @Column(nullable = false)
    private String title;

    // length 로 문자열 길이를 설정한다
    @Column(nullable = false)
    private String writer;

    @Lob
    private String contents;

    @Column(nullable = false)
    private LocalDateTime created;

    @PrePersist
    public void prePersist() {
        if (this.created == null) {
            this.created = LocalDateTime.now(); // 현재 시간으로 설정
        }
    }
}

 

GenerationType.AUTO JPA 에서 자동으로 기본 키를 생성해 주는 방법이다

사용하는 DB 에 맞추어

IDENTITY

SEQUENCE

TABLE
중에서 적절하게 생성해 준다

 

 

 

Oracle 에서 AUTO 를 사용하려 하니 방식이 명확하지 않아서 오류가 난다

Ms Sql 로 진행해 보자

 

 

저장 테스트

 

 

 

Ms Sql Table에는 IDENTITY 가 설정되어 있는데
IDENTITY 가 설정한 상태에서 AUTOInsert 를 하게 되면 

IDENTITY_INSERT 설정이 OFF 라서 저장이 안 된다고 한다

 

Table 에서 자동증가 IDENTITY 를 지우고 다시 저장 테스트를 해본다

 

 

저장은 되는데 -41 부터 저장이 되었다

구글링으론 정확한 글이 없어서 Chat GPT 를 이용해 보니

 

결국은 명시적으로 지정하라고 한다

 

 


 

GenerationType.IDENTITY 을 사용하는 경우

AUTO_INCREMENT 기능이 있는 Mysql , MariaDb, Sql Server 등은 잘 동작하지만

Oracle 에서는 해당 기능이 12c 이상부터 가능하며, 

대부분은 GenerationType.SEQUENCE 을 이용한다고 한다

참고하길 바란다

댓글