반응형
반응형
package com.lsj.blog;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.lsj.blog.repository.UserRepository;
import com.lsj.dto.ResponseDto;

@RestController
public class DummyController {

	@Autowired // DI
	private UserRepository userRepository;
	
	@PostMapping("/api/login")
	public ResponseDto<Integer> login(@RequestBody BlogUser user, HttpSession session){
		
		BlogUser principal = loginService(user); //principal (접근주체)
		if(principal != null) session.setAttribute("principal", principal);
		
		System.out.println("principal : " + session.getAttribute("principal"));
		
		return new ResponseDto<Integer>(HttpStatus.OK.value(), 1);
		
	}
	
	@Transactional(readOnly = true) // Select 할 때 트랜잭션 시작, 서비스 종료시 트랜잭션 종료 (데이터 일관성)
	public BlogUser loginService(BlogUser user) {
		return userRepository.findByUsernameAndPassword(user.getUsername(), user.getPassword());
	}
}
package com.lsj.blog.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.lsj.blog.BlogUser;


// extends JapRepository가 있는 경우 @Repository 생략가능
// JpaRepostiory는 다양한 기능을 가지고 있다. findAll (모든 레코드 select) 페이징해서 보내줄 수 있는 기능도 존재
public interface UserRepository extends JpaRepository<BlogUser, Integer>{ // BlogUser의 Repository이고 PK는 Integer이다.
	
	// JPA Naming 쿼리
	// SELECT * FROM bloguser WHERE username = ? AND password = ?;
	// SELECT * FROM ${리턴타입} WHERE username = ${첫번째 파라미터} AND password = ${두번째 파라미터};
	BlogUser findByUsernameAndPassword(String username, String password);
	
	// nativeQuery 방식 위와 동일하다
	@Query(value="SELECT * FROM bloguser WHERE username =1 ? AND password = 2?", nativeQuery = true)
	BlogUser login(String username, String password);
}
반응형
반응형

오라클의 경우 Read Commit 방식을 채택한다.

트랜잭션A가 시작되어 Update를 할 경우 Commit이 이루어질 때까지 UnDo의 영역을 읽기 때문에 Update하고 Commit의 사이에서 누군가 select할 시 1,000원이 출력된다.

 

트랜잭션A가 진행되면 누군가한테는 홍길동 누군가한테는 1,000원 누군가한테는 2,000원이 보일 수 있다.

이런식으로 보일 수 있기 때문에 정합성이 깨진다 → Phantom Read (데이터가 보였다 안 보였다)

 

이러한 점의 문제점은 트랜잭션 B와 같이 조회한 4개를 더해서 총 합을 구하는 시스템이라면 도중에 원래 기대값이 4,000원이지만 6,000원이 나오는 문제가 생긴다.

 

 

MySQL의 경우 Repeatable Read 방식을 채용한다.

UnDo 영역에 데이터를 읽고 자기 트랜잭션 번호보다 낮은 데이터를 읽기 때문에 중간에 Update를 해도 데이터의 일관성을 지킬 수 있다.

 

Insert, Select, Update, Delete의 경우 모두 @Transactional 이 필요하다

반응형
반응형
package com.lsj.blog;

import java.util.Random;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.lsj.blog.model.RoleType;
import com.lsj.blog.repository.UserRepository;
import com.lsj.dto.ResponseDto;

@RestController
public class DummyController {

	@Autowired // DI
	private UserRepository userRepository;
	
	@PostMapping("/api/user")
	@Transactional
	public ResponseDto<String> save(@RequestBody BlogUser user){

		BlogUser usre2 = new BlogUser();
		
		Random random = new Random();

		usre2.setUsername(String.valueOf(random.nextInt(10)));
		usre2.setPassword("12345"); 
		usre2.setEmail("abc@naver.com");
		userRepository.save(usre2); 
			
		new ResponseDto<String>(HttpStatus.OK.value(), "데이터 insert에 성공했습니다.");
		// HttpStatus.OK.value() → 200이라는 코드 반환 (정상 성공)
	}
}
package com.lsj.blog.handler;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import com.lsj.dto.ResponseDto;

@ControllerAdvice // 어떤 Exception이 오든 이 페이지로 오게 된다.
@RestController
public class GlobalExceptionHandler {
	
	@ExceptionHandler(value=Exception.class) // 모든 부모 Exception
	public ResponseDto<String> handleException(Exception e) {
		return new ResponseDto<String>(HttpStatus.INTERNAL_SERVER_ERROR.value(),e.getMessage());
		// HttpStatus.INTERNAL_SERVER_ERROR.value() → 500 코드 반환 (서버 에러)
		//return "<h1>" + e.getMessage() + "</h1>";
	}
}
package com.lsj.dto;

import org.springframework.http.HttpStatus;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ResponseDto<T> {
	int status;
//	HttpStatus status;
	T data;
}

 

반응형
반응형
package com.lsj.blog.handler; // Exception 처리 Handler를 따로 패키지를 구성한다.

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

@ControllerAdvice // 어떤 Exception이 오든 이 페이지로 오게 된다.
@RestController
public class GlobalExceptionHandler {
	
	// @ExceptionHandler는 Controller계층에서 발생하는 에러만 잡는다.
	@ExceptionHandler(value=Exception.class) // 모든 부모 Exception 
	public String handleException(Exception e) {
		return "<h1>" + e.getMessage() + "</h1>";
	}
	
	@ExceptionHandler(value=IllegalArgumentException.class) // 해당 IllegalArgumentException이 발생할 경우 밑에 함수가 작동한다.
	public String handleArgumentException(IllegalArgumentException e) {
		return "<h1>" + e.getMessage() + "</h1>";
	}
}
반응형
반응형
@DeleteMapping("dummy/user/{id}")
public String deleteUser(@PathVariable int id) {

    /** 방법1 (예외처리가 안 되어있음)**/
    //userRepository.deleteById(id);

     /** 방법2 **/
    try {
        userRepository.deleteById(id);
    }catch (Exception e) {
        return "삭제에 실패했습니다. 해당 id는 존재하지 않습니다.";
    }

    return "삭제되었습니다.";
}
반응형
반응형

 

영속성 컨텐스트란 엔티티를 영구 저장하는 환경으로 애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 데이터베이스라고 생각하면 된다.

JPA는 영속성 컨텍스트라는게 존재하고 그 안에 캐시가 있어서 DB에 접근 안 하고 캐시에 존재하는 데이터는 빠르게 가져오거나 DB에 부담을 줄일 수 있습니다. 그리고 그 캐시안에 있는 걸 영속화 되었다라고 표현합니다.

 

📝Insert

Insert시 영속성 컨텍스트에 해당 값이 올라가게 되고 flush해 영속성 컨텍스트에 있는 데이터를 DB에 데이터를 넣게 됩니다.

 

📝Select

Select시 DB에 해당 데이터를 영속성 컨텍스트에 올리게 됩니다. 그 후 컨트롤러에서는 영속성 컨텍스트에 있는 값을 가져가게 됩니다.

 

📝Update

Update의 경우 Select와 같은 동작이 선행이 되어서 영속성 컨텍스트에 올라가게 되고 그 후 업데이트된 값을 다시 영속화 시키고 DB에 flush해 데이터를 업데이트 시킵니다.

 

📝더티체킹

Update와 같은 행위를 Transaction 어노테이션을 이용해 하는 걸 더티체킹이라고 합니다.

Transaction 어노테이션이 선언된 곳에서 영속성 컨텍스트에 변경이 일어날 시 자동으로 데이터베이스에 반영하는 JPA 특징입니다.

 

 

@Transactional // 함수 종료시 자동으로 DB Commit (영속성컨테이너 데이터를 DB로 Flush)
// Update ( Put방식은 Body에 Json만 인식하고 @RequestBody는 두개 이상 사용이 불가능 (객체에 담던가 해야한다.)
@PutMapping("/dummy/users/{id}") 
public String updateUser(@PathVariable int id, @RequestBody BlogUser requestUser) {
    System.out.println("id : " + id);
    System.out.println("password : " + requestUser.getPassword());
    System.out.println("email : " + requestUser.getEmail());

    BlogUser user = userRepository.findById(id).orElseThrow(() ->{
        return new IllegalArgumentException("수정에 실패하였습니다.");
    });

    user.setPassword(requestUser.getPassword());
    user.setEmail(requestUser.getEmail());

    /** @Transactional 사용 안 할시 **/
    // save 함수는 id를 전달하지 않으면 insert
    // save 함수는 id를 전달하면 해당 id 존재시 udpate 없으면 insert
    // userRepository.save(user);

    return id + "가 update 가 되었습니다. ";
}

 

 

@Transaction 다른 예제

@RestController
public class DummyController {

	@Autowired // DI
	private UserRepository userRepository;
	
	@PostMapping("/api/user")
	//@Transacitonal
	public ResponseDto<String> save(@RequestBody BlogUser user){

		BlogUser usre2 = new BlogUser();
		
		Random random = new Random();

		usre2.setUsername(String.valueOf(random.nextInt(10)));
		usre2.setPassword("abc@naver.com");
		usre2.setEmail("abc@naver.com");
		userRepository.save(usre2); 
		
		user.setRole(RoleType.USER); // Enum을 이용한 방식을 통해 Setter 주입 실수를 방지할 수 있다. 
		join(user);
	
		return new ResponseDto<String>(HttpStatus.OK .value(), "1");
		// new ResponseDto<String>(HttpStatus.OK, result);
	}
	
	@Transactional // Transaction 처리하겠다. 성공시에만 Commit 
	public void join(BlogUser user) { 
		userRepository.save(user); // UserRepostiory에 save하면 DB 테이블에 insert가 된다.
	}
	
 }
 
 
 데이터 Body 형식 →
 {
    "username" : "lee6",
    "password" : "1234",
    "email" : "tjdwo37@naver.com"
}
 
 
 
 - @Transaction이 join 함수에 있는 경우
join 함수를 실행시에 에러가 날시 join함수 내용만 rollback
위에 랜덤함수로 UserName을 넣고 insert 과정은 join함수를 안 쓰기 때문에 
해당 API 계속 호출시 랜덤함수로 UserName 넣는 데이터 계속 insert는 되고 있음

- @Transcaation을 api 함수에 넣은 경우
api에서 에러가 날시 모든 내용을 rollback하기 때문에 위와 같이 랜덤함수로 UserName넣고 insert하는 과정도
rollback이 되어서 데이터가 계속 누적되지 않는다.
package com.lsj.blog;

import java.sql.Timestamp;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.DynamicInsert;

import com.lsj.blog.model.RoleType;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/** 하기 어노테이션 사용하려면 Javax Persistence API Gradle 추가 필요 **/
//@DynamicInsert // null 인 값일 때는 무시하고 Default값으로 넣어준다
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity // 하기 필드 기준으로 DB에  User 테이블을 생성하라는 의미
public class BlogUser {

	@Id // Primary key
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 프로젝트에서 연결된 DB의 넘버링 전략을 따라간다.
	// → 즉, DB에 따라 AutoIncrement 또는 Sequence가 결정 되어서 알아서 만들어준다. (자동 증가 PK 필요함으로 이와 같은 행동 함) 
	// (MySql에서는 AutoIncrement, Oracle에서는 Sequence 사용)
	private int id;
	
	@Column(nullable = false, length = 30, unique=true) // null 방지 및 길이 30 + 중복값 방지
	private String username;
	
	//@ColumnDefault(" 'no password' ") //→ @DynamicInsert 와 같이 사용한다. null일시에는 ColumnDefault에 선언된 값(no password)으로 넣어준다.   
	@Column(nullable = false, length = 100) 
	private String password;

	@Column(nullable = false, length = 50) 
	private String email;
	
	//@ColumnDefault("'user'") // → Column Default 값 String이기 때문에 ' ' 안에 넣어야한다.
	//private String role; // Enum을 
	
	@Enumerated(EnumType.STRING) // DB에는 RoleType이라는 타입이 없기 때문에 String 이라고 선언
	private RoleType role;
	
	@CreationTimestamp // 현재 시각 바로 자동 입력
	private Timestamp createDate;
	
}

 

반응형
반응형
import java.util.List;
import java.util.function.Supplier;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.lsj.blog.model.RoleType;
import com.lsj.blog.repository.UserRepository;


@GetMapping("/dummy/user/{id}")
public BlogUser detail(@PathVariable int id) { // PathVariable은 들어온 id값에 따른 동적 처리 {id}


    // BlogUser user = userRepository.findById(id); // findById의 return 타입은 Optional
                                                    // → 자바에서 DB 데이터를 못찾아오게 되면 user가 null이 되어 return이 되기 때문에
                                                    // Optional로 객체를 감싸서 가져올테니 null인지 아닌지 판단해서 return 해라
    /** 방법1 **/
    // userRepository.findById(id).get(); // null 그런거 상관없이 가져오겠다. (위험) 

    /**  방법 2
    BlogUser user = userRepository.findById(id).orElseGet(new Supplier<BlogUser>(){
        @Override
        public BlogUser get() { // 값이 없는 경우 BlogUser 객체 생성해 주입 (Null 가능성은 없음)
            return new BlogUser();
        }
    });
    **/

    /** 방법3 (선호) 해당 에러 발생시 Throw **/
    BlogUser user = userRepository.findById(id).orElseThrow(new Supplier<IllegalArgumentException>(){
        @Override
        public IllegalArgumentException get() {
            return new IllegalArgumentException("해당 유저는 없습니다. id : " + id);
        }
    });

    return user;
}

// 페이지리스트 모두 출력
@GetMapping("/dummy/list")
public List<BlogUser> list(){
    return userRepository.findAll();
}

// 페이지네이션
// size → 보여줄 개수
// sort → order by 할 필드
// direction  → 오름차순 또는 내림차순
// dummy/list/page?page=0 일시 id 3번, 2번 노출  | page=1로 호출시 id 1번 노출
// 아무것도 입력안 할시 ?page=0과 동일
@GetMapping("dummy/list/page")
public Page<BlogUser> pageList(@PageableDefault(size=2, sort="id", direction = Sort.Direction.DESC) Pageable pageable){
    Page<BlogUser> users = userRepository.findAll(pageable);
    return users;
}

 

반응형
반응형
package com.lsj.blog;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.lsj.blog.model.RoleType;
import com.lsj.blog.repository.UserRepository;

@RestController
public class DummyController {

	@Autowired // DI
	private UserRepository userRepository;
	
	@PostMapping("/dummy/join")
	public String join(BlogUser user) { 
		
		//user.setRole("user"); // @DynamicInsert처럼 계속 어노테이션을 붙히다보면 어노테이션 지옥에 빠지기 때문에 직접 Setter에 주입해 어노테이션을 줄일 수 있지만 실수할 수 있다.
		user.setRole(RoleType.USER); // Enum을 이용한 방식을 통해 Setter 주입 실수를 방지할 수 있다. 
		userRepository.save(user); // UserRepostiory에 save하면 DB 테이블에 insert가 된다.
		
		return "회원가입이 완료되었습니다.";
	}
}

DummyController.java

 

package com.lsj.blog.model;

//데이터 강제할 수 있다. (데이터의 도메인화 → 강제)
public enum RoleType {
	USER, 
	ADMIN 
}

RoleType.java

 

package com.lsj.blog.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.lsj.blog.BlogUser;

// extends JapRepository가 있는 경우 @Repository 생략가능
// JpaRepostiory는 다양한 기능을 가지고 있다. findAll (모든 레코드 select) 페이징해서 보내줄 수 있는 기능도 존재
public interface UserRepository extends JpaRepository<BlogUser, Integer>{ // BlogUser의 Repository이고 PK는 Integer이다.
	
}

UserRepository.java

 

package com.lsj.blog;

import java.sql.Timestamp;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.DynamicInsert;

import com.lsj.blog.model.RoleType;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/** 하기 어노테이션 사용하려면 Javax Persistence API Gradle 추가 필요 **/
@DynamicInsert // null 인 값일 때는 무시하고 Default값으로 넣어준다
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity // 하기 필드 기준으로 DB에  User 테이블을 생성하라는 의미
public class BlogUser {

	@Id // Primary key
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 프로젝트에서 연결된 DB의 넘버링 전략을 따라간다.
	// → 즉, DB에 따라 AutoIncrement 또는 Sequence가 결정 되어서 알아서 만들어준다. (자동 증가 PK 필요함으로 이와 같은 행동 함) 
	// (MySql에서는 AutoIncrement, Oracle에서는 Sequence 사용)
	private int id;
	
	@Column(nullable = false, length = 30, unique=true) // null 방지 및 길이 30 + 중복값 방지
	private String username;
	
	@ColumnDefault(" 'no password' ") //→ @DynamicInsert 와 같이 사용한다. null일시에는 ColumnDefault에 선언된 값(no password)으로 넣어준다.   
	@Column(nullable = true, length = 100) 
	private String password;

	@Column(nullable = false, length = 50) 
	private String email;
	
	//@ColumnDefault("'user'") // → Column Default 값 String이기 때문에 ' ' 안에 넣어야한다.
	//private String role; // Enum을 
	
	@Enumerated(EnumType.STRING) // DB에는 RoleType이라는 타입이 없기 때문에 String 이라고 선언
	private RoleType role;
	
	@CreationTimestamp // 현재 시각 바로 자동 입력
	private Timestamp createDate;
	
}


/**
위와 같은 엔터티일 때 세이브할 데이터 형식 예제
{
    "username" : "lee6",
    "email" : "abc@naver.com"
}

결과 → 2	22/12/03 12:31:26.986000000	tjdwo37@naver.com	no password	USER	lee6
**/

BlogUser.java

반응형
반응형

 

plugins {
	id 'org.springframework.boot' version '2.7.4'
	id 'io.spring.dependency-management' version '1.0.14.RELEASE'
	id 'java'
}

group = 'com.lsj'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	/** 추가 라이브러리 **/
	// https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper
	implementation 'org.apache.tomcat.embed:tomcat-embed-jasper:9.0.58'

	// https://mvnrepository.com/artifact/javax.persistence/javax.persistence-api
	implementation group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2'

	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'com.oracle.database.jdbc:ojdbc8'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.security:spring-security-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

gradle 설정입니다.

package com.lsj.chatting;

import java.sql.Timestamp;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;

/** 하기 어노테이션 사용하려면 Javax Persistence API Gradle 추가 필요 **/
@Entity // 하기 필드 기준으로 DB에  User 테이블을 생성하라는 의미
public class BlogUser {

	@Id // Primary key
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 프로젝트에서 연결된 DB의 넘버링 전략을 따라간다.
	// → 즉, DB에 따라 AutoIncrement 또는 Sequence가 결정 되어서 알아서 만들어준다. (자동 증가 PK 필요함으로 이와 같은 행동 함) 
	// (MySql에서는 AutoIncrement, Oracle에서는 Sequence 사용)
	private int id;
	
	@Column(nullable = false, length = 30) // null 방지 및 길이 30
	private String username;
	
	@Column(nullable = false, length = 100) 
	private String password;
	
	@Column(nullable = false, length = 50) 
	private String email;
	
	@ColumnDefault("'user'") // → Column Default 값 String이기 때문에 ' ' 안에 넣어야한다.
	private String role; // Enum을 
	// → admin : 0
	// → user : 0
	// → manager : 0
	
	@CreationTimestamp // 현재 시각 바로 자동 입력
	private Timestamp createDate;
	
}

어노테이션을 이용해 테이블 생성하기 위한 Java 파일 입니다.

server:
  port: 8000 # 톰캣 포트 (스프링부트는 톰캣이 내장되어 있다.)
  servlet:
    context-path: /chatting # 기본 url Path 
    encoding:
      charset: UTF-8
      enabled: true
      force: true
    
spring:
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp 
      # @GetMapping 에서 함수의 return 값이 String인 경우 return 에 대한 내용은 jsp의 파일 이름입니다.
      # @GetMapping 
      # public String callJsp(){
      #   return "home" → /WEB-INF/views/home.jsp 화면을 뿌려라 
      #   일반적으로 스프링부트는 JSP를 지원하지 않기 때문에 JSP를 사용하기 위해서는 JSP 해석 템플릿 엔진인 jasper을 Gradle에서 다운로드를 해야한다.
      #}
  
  datasource:
    driver-class-name: oracle.jdbc.OracleDriver
    url: jdbc:oracle:thin:@localhost:1521:orcl
    username: c##root
    password: 1234
    
  jpa:
    open-in-view: true
    hibernate:
      ddl-auto: create # 최초 전략 Applicaiton 재시작시 테이블 있으면 지우고 다시 만들게 된다.
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        # field 명 그대로 필드를 만들게 된다.
        # physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
        # CamelCase 전략을 따라가는데 field 명이 myEmail인 경우 my_email로 변환시켜서 만들어준다. 
      use-new-id-generator-mappings: false 
      # false : JPA 기본 전략을 쓴다. 
      # false : JPA 기본 전략을 쓰지 않는다. → User에 선언한 GenerationType.IDENTITY을 쓰겠다
    show-sql: true
    properties:
      hibernate.format_sql: true

  jackson:
    serialization:
      fail-on-empty-beans: false

yml 파일로 JPA 사용할 설정이 들어있습니다.

 

Hibernate: 
    
    drop table BlogUser cascade constraints
Hibernate: 
    
    create table BlogUser (
       id number(10,0) generated as identity,
        createDate timestamp,
        email varchar2(50 char) not null,
        password varchar2(100 char) not null,
        role varchar2(255 char) default 'user',
        username varchar2(30 char) not null,
        primary key (id)
    )

시작시 Hibernate라는 애가 Java 파일 설정을 읽어서 Query를 생성시켜줍니다.

반응형