(JPA학원/추천JPA교육)Spring Data JPA 식별자 자동생성, 스프링 부트, 오라클 기반 예제, @Generated…

FSP 0 148 2018.12.14 11:04

(JPA학원/추천JPA교육)Spring Data JPA 식별자 자동생성, 스프링 부트, 오라클 기반 예제, @GeneratedValue



JPA 식별자 자동 생성(@GeneratedValue)

https://youtu.be/2zovSWrKhmo



n  식별자 자동생성은 @GeneratedValue 어노테이션으로 지정한다.
n  복합키 보다는 대행키(인공키, Artifitial Key) 사용을 권장한다.
n  @GeneratedValue strategy 속성에 값을 지정해 여러 가지 식별자 자동 생성 전략을 선택할 수 있는데 AUTO, TABLE, SEQUENCE, IDENTITY 값으로 지정한다이 값들은 열거형인 GenerationType에 정의되어 있다.
n   GenerationType.AUTO : 데이터베이스에 관계없이 식별자를 자동 생성 하라는 의미,  DB가 변경되더라도 수정할 필요 없다.
 
자동 선택
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="USER_ID")
protected Long userId;
 
JPA 공급자에 따라 기본설정이 다름
ü  Oracle을 사용할 경우 SEQUENCE가 기본
ü  MS SQL Server의 경우 IDENTITY가 기본
 
위 예문의 경우 오라클이라면 하이버네이트 글로벌 시퀀스(hibernate_sequence)를 사용하므로 엔티티에서  두 군데 이상 AUTO로 사용한다면 시퀀스를 별도로 만들고 명시적으로 SequenceGenerator를 기술하여 사용하는 것이 좋다.
 
n  GenerationType.TABLE : 가장 유연하고 이식성이 좋은 방법으로 키를 위한 테이블이 생성되어 있어야 하며, ID 생성 테이블은 두 개의 칼럼을 반드시 가져야 한다처음 컬럼은 특정 시퀀스를 식별하는데 사용되는 문자열 타입이고 모든 Generator를 위한 위한 주키다두 번째 칼럼은 생성되고 있는 실제 ID 값인 시퀀스를 저장하는 숫자 타입으로 이 칼럼에 저장되는 값은 시퀀스에 할당되었던 마지막 값이 된다하나의 테이블에 여러 식별자 값을 저장할 수 있으며 오라클의 경우 아래처럼 사용하면 된다.
 
1. 식별자용 테이블 생성(JPA에서 자동생성)
CREATE TABLE SEQ_TABLE
(SEQ_NAME VARCHAR2(100) NOT NULL PRIMARY KEY,  
SEQ_VALUE NUMBER NOT NULL);
 
2. 식별자 테이블 초기화(JPA에서 자동생성)
INSERT INTO SEQ_TABLE VALUES ('USER_SEQ', 1);
 
3. TableGenerator 생성, @GeneratedValue 사용
@TableGenerator (name="MY_GENERATOR", table="SEQ_TABLE", pkColumnName="SEQ_NAME",
valueColumnName="SEQ_VALUE", pkColumnValue="USER_SEQ") 
@Entity
public class User {
@GeneratedValue(strategy=GenerationType.TABLE, generator="MY_GENERATOR")
@Column(name="USER_ID")
@Id
protected Long userId;
 
n  GenerationType.SEQUENCE : DB에서 생성해 놓은 시퀀스를 이용하는 방법으로 오라클, DB2, PostgreSQL, H2 데이터베이스 등에서 사용한다.
 
1. 오라클 DB에 시퀀스 생성
CREATE SEQUENCE USER_SEQ;
 
2. 엔티티에 SequenceGenerator,  @GeneratedValue 지정
@SequenceGenerator(name="USER_SEQ_GENERATOR", sequenceName="USER_SEQ")§
@Id
@Entity
public class User {
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="USER_SEQ_GENERATOR")
@Column(name="USER_ID")
protected Long userId;
 
n  GeneratedType.IDENTITY : MySQL, MS-SQL 처럼 DB 자체적으로 식별자 칼럼에 자동증분 속성이 있는 경우에 사용한다엔티티의 주키 컬럼을 위한 정의는 DB 스키마 정의의 일부분으로 정의되어야 한다
 
[GenerationType.TABLE, 오라클 예제]
STS에서 File -> New -> Spring Stater Project 프로젝트 이름 : GeneratedValueTest
다음화면에서 SQL : JPA, Web : Web 선택
 
1. pom.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
         <modelVersion>4.0.0</modelVersion>
 
         <groupId>com.example</groupId>
         <artifactId>demo</artifactId>
         <version>0.0.1-SNAPSHOT</version>
         <packaging>jar</packaging>
 
         <name>GeneratedValueTest</name>
         <description>Demo project for Spring Boot</description>
 
         <parent>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-parent</artifactId>
                  <version>1.4.1.RELEASE</version>
                  <relativePath /> <!-- lookup parent from repository -->
         </parent>
 
         <dependencies>
                  <dependency>
                           <groupId>org.springframework.boot</groupId>
                           <artifactId>spring-boot-starter-data-jpa</artifactId>
                  </dependency>
                  <dependency>
                           <groupId>org.springframework.boot</groupId>
                           <artifactId>spring-boot-starter-web</artifactId>
                  </dependency>
 
                  <dependency>
                           <groupId>org.springframework.boot</groupId>
                           <artifactId>spring-boot-starter-test</artifactId>
                           <scope>test</scope>
                  </dependency>
 
                  <!-- JSP, JSTL 사용위해 -->
                  <dependency>
                           <groupId>javax.servlet</groupId>
                           <artifactId>jstl</artifactId>
                  </dependency>
                  <dependency>
                           <groupId>org.apache.tomcat.embed</groupId>
                           <artifactId>tomcat-embed-jasper</artifactId>
                           <scope>provided</scope>
                  </dependency>
 
                  <!-- DriverSpy -->
                  <dependency>
                           <groupId>org.bgee.log4jdbc-log4j2</groupId>
                           <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
                           <version>1.16</version>
                  </dependency>
 
                  <!-- for oracle -->
                  <dependency>
                           <groupId>com.oracle</groupId>
                           <artifactId>ojdbc6</artifactId>
                           <version>11.1.0.7.0</version>
                  </dependency>       
         </dependencies>
 
         <build>
                  <plugins>
                           <plugin>
                                    <groupId>org.springframework.boot</groupId>
                                    <artifactId>spring-boot-maven-plugin</artifactId>
                           </plugin>
                  </plugins>
         </build>
 
         <repositories>
                  <repository>
                           <id>oracle</id>
                           <name>ORACLE JDBC Repository</name>
                           <url>https://maven.oracle.com</url>;
                  </repository>
         </repositories>       
</project>
 
2. application.properties
 
spring.datasource.platform=oracle
spring.datasource.sql-script-encoding=UTF-8
spring.datasource.url=jdbc:log4jdbc:oracle:thin:@localhost:1521:onj
spring.datasource.username=test
spring.datasource.password=test
#spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.driver-class-name = net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
 
#hibernate config
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
logging.level.jpa=DEBUG
 
#view
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
 
3. log4jdbc.log4j2.properties
 
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
log4jdbc.dump.sql.maxlinelength=0
 
4. logback.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">    
    <encoder>
      <pattern>%d{yyyyMMdd HH:mm:ss.SSS} [%thread] %-3level %logger{5} - %msg %n</pattern>
    </encoder>
  </appender>
  
  <logger name="jdbc" level="OFF"/>
  
  <logger name="jdbc.sqlonly" level="DEBUG" additivity="false">>
    <appender-ref ref="STDOUT" />
  </logger>
  
  <logger name="jdbc.sqltiming" level="INFO" additivity="false">>
    <appender-ref ref="STDOUT" />
  </logger>   
  
  <logger name="jdbc.resultsettable" level="DEBUG" additivity="false">> 
    <appender-ref ref="STDOUT" />
  </logger>  
  
  <root level="INFO">
    <appender-ref ref="STDOUT" />
  </root>  
</configuration>
 
5. User.java
 
package com.example.model;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.TableGenerator;
 
@TableGenerator(name = "MY_GENERATOR", table = "SEQ_TABLE", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_VALUE", pkColumnValue = "USER_SEQ")
@Entity(name="MyUser")
public class User {
         @GeneratedValue(strategy = GenerationType.TABLE, generator = "MY_GENERATOR")
         @Id
         private Long userId;
         
         @Column
         private String userName;
         
         public User(String userName) {
                  this.userName = userName;
         }
         
         public User() {}
 
         public Long getUserId() {
                  return userId;
         }
 
         public void setUserId(Long userId) {
                  this.userId = userId;
         }
 
         public String getUserName() {
                  return userName;
         }
 
         public void setUserName(String userName) {
                  this.userName = userName;
         }
         
}
 
 
6. UserRepository.java
 
package com.example.repository;
 
import org.springframework.data.jpa.repository.JpaRepository;
 
import com.example.model.User;
 
public interface UserRepository 
               extends JpaRepository<User, Long> {
}
 
7. UserService.java
 
package com.example.service;
 
import java.util.List;
 
import com.example.model.User;
 
public interface UserService {
         User get(Long userId);
         User save(User user);
         List<User> getAll();   
}
 
8. UserServiceImpl.java
 
package com.example.service;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.example.model.User;
import com.example.repository.UserRepository;
 
@Service
public class UserServiceImpl implements UserService {
 
         @Autowired
         UserRepository userRepository;
         
         @Override
         public User get(Long userId) {                 
                  return userRepository.findOne(userId);
         }
 
         @Override
         public User save(User user) {
                  return userRepository.save(user);
         }
 
         @Override
         public List<User> getAll() {
                  return userRepository.findAll();                
         }        
}
 
9. UserController.java
 
package com.example.controller;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import com.example.model.User;
import com.example.service.UserService;
 
@RestController
public class UserController { 
         @Autowired
         private UserService userService;
         
         @RequestMapping(value="/get/{userId}", method=RequestMethod.GET)
         public User get(@PathVariable Long userId) {
                  return userService.get(userId);
         }
         
         @RequestMapping(value="/save/{userName}", method=RequestMethod.GET)
         public User save(@PathVariable String userName) {
                  return userService.save(new User(userName));
         }
         
         @RequestMapping(value="/getall", method=RequestMethod.GET)
         public List<User> getAll() {
                  return userService.getAll();
         }        
}
 
10. 오라클에 식별자를 위한 테이블 및 데이터 생성
 
SQL> create table seq_table (
  2  seq_name varchar2(100) primary key,
  3  seq_value number not null);
 
테이블이 생성되었습니다.
 
SQL> INSERT INTO SEQ_TABLE VALUES ('USER_SEQ', 1);
 
개의 행이 만들어졌습니다.
 
SQL> commit;
 
커밋이 완료되었습니다.
 
 
11. 실행결과
 



 
 


 

, , , , , , , , , , , , , , , , , , , , , , , , , , , ,

Comments