728x90
반응형

[Spring Boot] JPA(Hibernate) 적용

 

환경 : Spring Boot 2.6.4, MySQL 5.7, Spring-data-jpa, Lombok

 

ORM(Object Relational Mapping) : 객체와 관계형 데이터베이스의 데이터를 자동으로 연결해주는 것

JPA(Java Persistence API) : 자바에서의 ORM을 위한 표준 기술 명세이자 인터페이스의 모음

Hibernate : JPA의 구현체 ( EclipseLink, DataNucleus 도 존재하나, Hibernate 가 메인 ) 

Spring-data-jpa : JPA 사용을 도와주는 모듈, 내부적으로 Hibernate를 사용

Repository : Spring-data-jpa 모듈에서 제공하는 JPA를 한단계 추상화시킨 인터페이스

 

 

0. Lombok 및 프로젝트 기본 설정 

 

 

1. Gradle 설정

spring-data-jpa 및 MySQL Connector 의존성 추가

dependencies {

..

   implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

   compile("mysql:mysql-connector-java:5.1.34")

..

}

 

추가 후 Gradle Sync or Refresh

 

 

2. application.properties 설정

 

DB 정보 추가

# 각 행 뒤에 공백 주의!

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://'DB-EndPoint':'Port'/'DBName'
spring.datasource.username=dbUser 
spring.datasource.password=dbPassword 
# 각 환경에 맞게 수정 필요


spring.jpa.properties.hibernate.format_sql=true
# 정렬된 SQL 출력  

spring.jpa.show-sql=true
# 사용되는 SQL 콘솔창에 출력

spring.jpa.hibernate.ddl-auto=create
# 객체에 매핑되는 기존 테이블 자동 드랍 및 새로운 테이블 생성

 

 

3. 객체(모델) 생성

 

Product.java

package com.example.demo;

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

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class Product {
    @Id
    @GeneratedValue // Auto IncId Generator
    private Long id;

    @Column(length = 20, nullable = false)
    private String name;

    @Column(columnDefinition = "TEXT", nullable = true)
    private Integer price;

    private String memo;

    @Builder
    public Product(String name, Integer price, String memo) {
        this.name = name;
        this.price = price;
        this.memo = memo;
    }
}

 

4. Repository 생성

 

ProductRepository.java

package com.example.demo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long>{

}

 

 

5. 확인

4. 까지 설정 후 어플리케이션을 실행하면 해당 데이터베이스에 자동으로 객체에 매핑되는 테이블이 생성된다

 

콘솔

MySQL 

product 테이블 및 객체에 선언했던 id,memo,name,price 칼럼 생성

@GeneratedValue에 의한 Auto Inc Sequence용 hibernate_sequence 테이블생성

 

 

6. CRUD 사용 예시

 

In Controller

@RestController
public class ProductController {

@Autowired
private ProductRepository productRepository;

..

..

}

 

6-1. Create

 

In Controller

...

@GetMapping("/create")  
public void create(Product product) {
productRepository.save(product);
}

...

 

URL로 접근

 

Console

In DB

 

 

 

6-2. Read

 

In Controller

..

@GetMapping("/readOne")
public Optional readOne(Long id) {
return productRepository.findById(id);
}

@GetMapping("/readAll")
public List readAll() {
return productRepository.findAll();
}

..

 

URL 접근

readAll의 경우 리스트 형태로 온 것을 확인 가능 ( '[ ]' )

 

In Console

 

6-3. Update

Update의 경우 PK를 지정하여 save를 하거나, 직접 만든 쿼리를 사용하며, 해당 과정에서는 직접 만든 쿼리를 사용

 

In Controller

..

@GetMapping("/update")
public void update(Product product, Long id) {
productRepository.update(product, id);
}

..

 

In Repository

..

@Modifying
@Transactional
@Query(value="UPDATE mydbinstance.product m SET m.name=:#{#product.name}, m.memo=:#{#product.memo}, m.price=:#{#product.price} WHERE m.id = :id", nativeQuery=true)
void update(@Param("product") Product product, @Param("id") Long id);

 

..

 

URL 접근

 

Console

In DB

수정 전

 

수정 후

 

 

6-4. Delete

 

In Controller

..

@GetMapping("/delete")
public void delete(Long id) {
productRepository.deleteById(id);
}

..

URL 접근

 

Console

 

In DB

삭제 전

삭제 후

 

---

 

전체 소스

 

Product.java

package com.example.demo; 

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

import lombok.AccessLevel; 
import lombok.Builder; 
import lombok.Getter; 
import lombok.NoArgsConstructor; 

@NoArgsConstructor(access = AccessLevel.PROTECTED) 
@Getter 
@Entity 
public class Product { 
    @Id 
    @GeneratedValue 
    private Long id; 

    @Column(length = 20, nullable = false) 
    private String name; 

    @Column(nullable = false) 
    private Integer price; 

    @Column(nullable = true)
    private String memo; 

    @Builder 
    public Product(String name, Integer price, String memo) { 
        this.name = name; 
        this.price = price; 
        this.memo = memo; 
    } 
}

 

ProductController.java

package com.example.demo;

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

import java.util.List;
import java.util.Optional;

@RestController
public class ProductController {

@Autowired
private ProductRepository productRepository;

@GetMapping("/hello")
public String hello() {
return "Hello World";
}

@GetMapping("/create")
public void create(Product product) {
productRepository.save(product);
}

@GetMapping("/readOne")
public Optional readOne(Long id) {
return productRepository.findById(id);
}

@GetMapping("/readAll")
public List readAll() {
return productRepository.findAll();
}

@GetMapping("/update")
public void update(Product product, Long id) {
productRepository.update(product, id);
}

@GetMapping("/delete")
public void delete(Long id) {
productRepository.deleteById(id);
}
}

 

ProductRepository.java

package com.example.demo; 
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional; 

public interface ProductRepository extends JpaRepository<Product, Long>{ 

@Modifying
@Transactional
@Query(value="UPDATE mydbinstance.product m SET m.name=:#{#product.name}, m.memo=:#{#product.memo}, m.price=:#{#product.price} WHERE m.id = :id", nativeQuery=true)
void update(@Param("product") Product product, @Param("id") Long id);

 

build.gradle

plugins {
id 'org.springframework.boot' version '2.1.6.RELEASE'
id 'java'
}

apply plugin: 'io.spring.dependency-management'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
mavenCentral()
}

configurations { compileOnly { extendsFrom annotationProcessor } }

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    compile("mysql:mysql-connector-java:5.1.34")
    
    compileOnly 'org.projectlombok:lombok' 
annotationProcessor 'org.projectlombok:lombok'
}

 

application.properties

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://mydbinstance.ctueexvldsoh.ap-northeast-2.rds.amazonaws.com:3306/mydbinstance
spring.datasource.username=qwe
spring.datasource.password=qweqweqwe
# 각 환경에 맞게 수정 필요


spring.jpa.properties.hibernate.format_sql=true
# 정렬된 SQL 출력  

spring.jpa.show-sql=true
# 사용되는 SQL 콘솔창에 출력

spring.jpa.hibernate.ddl-auto=create
# 객체에 매핑되는 기존 테이블 자동 드랍 및 새로운 테이블 생성

 

모든 java파일은 ProjectAppication.java과 같거나 하위폴더에 생성

 

728x90
반응형

'Java' 카테고리의 다른 글

[spring boot] AOP 설정  (0) 2019.07.21
[Spring Boot-Vue] 프로젝트 빌드  (0) 2019.07.21
[Spring Boot] Eclipse 내 Lombok 설치  (0) 2019.07.05
[Spring Boot] 개발 환경 세팅  (2) 2019.07.05
[spring] Controller -> JSP 데이터 전달  (0) 2019.06.28

+ Recent posts