이번 가이드는 Spring Data JPA를 사용하여 관계 데이터를 관계형 데이터 베이스에 저장하는 것을 실습하겠습니다!
우리가 만들 것?
우리는 Customer POJO(plain Old Java Objects)를 만들고 실제 데이터베이스에 저장하면서 관리하는 Application을 만들겠습니다.
필요한 것
- 약 15분의 시간
- 가장 자주 사용하는 IDE
- JDK 1.8 이상
- Gradle 4+ or Maven 3.2+
Spring Initializr로 프로젝트를 생성
의존성은 Spring Data JPA와 H2 Database 두 가지를 추가해 줍니다.
Spring Initializr는 프로젝트 이름으로 작성되어 압축되어 있기 때문에
대상 폴더의 하위에 '압축 파일명'으로 폴더 생성 후 압축 풀기(E) 체크박스 해제 후 작업할 workspace에 풀기.
프로젝트 폴더를 본인에게 편한 방법으로 열기!
성공적으로 단계를 진행했다면, pom.xml이 다음과 같은 의존성을 포함하고 있을 것입니다.
plugins {
id 'org.springframework.boot' version '2.2.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
간단한 객체 정의
이번 가이드에서 우리는 Customer 객체에 데이터를 저장 할 것이고, JPA 어노테이션으로 연결 할 것 입니다.
package com.example.accessingdatajpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
protected Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format(
"Customer[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
위 코드를 살펴보면 Customer 클래스에 세 가지 속성이 작성된 것을 볼 수 있습니다. 순서대로 id, firstName, lastName 입니다. 또한 두개의 생성자가 있습니다. 기본 생성자는 JPA를 위해 존재합니다. 직접적으로 사용하지 않음으로 protect로 합니다. 다른 생성자는 데이터베이스에 저장할 고객의 인스턴스를 생성하는 데 사용하는 것입니다.
Customer 클래스는 @Entity 어노테이션이 되어 있습니다. JPA엔티티임을 나타내는 어노테이션입니다.
(@Table 어노테이션이 없으므로 이 엔티티가 Customer라는 테이블에 매핑된 것으로 가정합니다.)
Customer 객체의 id 속성은 @Id로 주석을 달아서 JPA가 객체의 id로 인식합니다. id속성은 id가 자동으로 생성되어야 함을 나타내기 위해 @GeneratedValue로 어노테이션을 달기도 합니다.
나머지 두 열은 동일한 이름의 column에 맵핑됩니다.
간단한 쿼리문 만들기
Spring Data JPA를 사용하여 데이터를 관계형 데이터베이스에 저장하는데 초점을 둡니다 .가장 매력적인 기능은 저장소 인터페이스에서 런타임에 저장소 구현을 자동으로 생성할 수 있는 기능입니다.
저장소 인터페이스는 아래와 같이 구동합니다.
package com.example.accessingdatajpa;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
Customer findById(long id);
}
CustomerRepository는 CrudRepository 인터페이스를 상속받습니다. 함께 작동하는 객체 및 ID의 유형(Customer 및 long)은 CrudRepository의 일반 매개 변수에 지정되어 있습니다. CrudRepository를 확장함으로써 CustomerRepository는 고객 엔티티를 저장, 삭제 및 찾는 방법을 포함하여 고객 지속성을 위한 몇 가지 방법을 상속합니다.
Spring Data JPA를 사용하면 메서드를 선언하여 다른 쿼리 방법을 정의할 수도 있습니다. 예를 들어 CustomerRepository에는 findByLastName() 메서드가 포함됩니다.
일반적인 Java 애플리케이션에서는 CustomerRepository를 구현하는 클래스를 작성할 수 있습니다. 그러나 이러한 이유로 Spring Data JPA가 매우 강력해집니다. 리포지토리 인터페이스의 구현을 작성할 필요는 없습니다. Spring Data JPA는 애플리케이션을 실행할 때 알아서 구현합니다.
package com.example.accessingdatajpa;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class AccessingDataJpaApplication {
private static final Logger log = LoggerFactory.getLogger(AccessingDataJpaApplication.class);
public static void main(String[] args) {
SpringApplication.run(AccessingDataJpaApplication.class);
}
@Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a few customers
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
repository.save(new Customer("Kim", "Bauer"));
repository.save(new Customer("David", "Palmer"));
repository.save(new Customer("Michelle", "Dessler"));
// fetch all customers
log.info("Customers found with findAll():");
log.info("-------------------------------");
for (Customer customer : repository.findAll()) {
log.info(customer.toString());
}
log.info("");
// fetch an individual customer by ID
Customer customer = repository.findById(1L);
log.info("Customer found with findById(1L):");
log.info("--------------------------------");
log.info(customer.toString());
log.info("");
// fetch customers by last name
log.info("Customer found with findByLastName('Bauer'):");
log.info("--------------------------------------------");
repository.findByLastName("Bauer").forEach(bauer -> {
log.info(bauer.toString());
});
// for (Customer bauer : repository.findByLastName("Bauer")) {
// log.info(bauer.toString());
// }
log.info("");
};
}
}
@SpringBootApplication은 아래 내용을 모두 추가한 편의 어노테이션입니다.
-@Configuration: 클래스를 응용 프로그램 컨텍스트에 대한 bean 정의 소스로 태그합니다.
-@EnableAutoConfiguration은 다음과 같습니다. 스프링 부트에게 클래스 경로 설정, 다른 bean 및 다양한 속성 설정에 따라 bean 추가를 시작하라고 말합니다. 예를 들어, spring-webmvc가 classpath에 있는 경우 이 주석에서는 응용 프로그램을 웹 응용 프로그램으로 플래그 지정하고 DispatcherServlet 설정과 같은 주요 동작을 활성화합니다.
-@ComponentScan은 다음과 같습니다. Spring은 com/example 패키지에서 다른 구성 요소, 구성 및 서비스를 검색하여 컨트롤러를 찾을 수 있도록 합니다.
애플리케이션에는 CustomerRepository에 몇 가지 테스트를 수행하는 Demo() 방법이 포함되어 있습니다. 첫째, Spring 애플리케이션 컨텍스트에서 CustomerRepository를 가져옵니다. 그런 다음, 몇 개의 고객 개체를 저장하여 save() 방법을 시연하고 작업할 데이터를 설정합니다. 그런 다음 findAll()을 호출하여 데이터베이스에서 모든 고객 객체를 가져옵니다. 그런 다음 findOne()을 호출하여 ID로 단일 고객을 가져옵니다. 마지막으로 findByLastName()을(를) 호출하여 성이 "Bauer"인 모든 고객을 찾습니다. Demo() 방법은 응용 프로그램이 시작될 때 자동으로 코드를 실행하는 CommandLineRunner Bin을 반환합니다.
AccessingDataJpaApplication 클래스는 CustomerRepository에 몇 가지 테스트를 수행하는 main() 메서드를 포함합니다. 첫째, Spring 애플리케이션 컨텍스트에서 CustomerRepository를 가져옵니다. 그런 다음 몇 가지 고객 개체를 저장하여 save() 방법을 시연하고 사용할 데이터를 설정합니다. 그런 다음 findAll()을 호출하여 데이터베이스에서 모든 고객 객체를 가져옵니다. 그런 다음 findOne()을 호출하여 ID로 단일 고객을 가져옵니다. 마지막으로 findByLastName()을 호출하여 성이 "Bauer"인 모든 고객을 찾습니다.
기본적으로 Spring Boot는 JPA 리포지토리를 지원하고 @SpringBootApplication이 있는 패키지(및 해당 하위 패키지)를 찾습니다. 구성에 표시되지 않는 패키지에 JPA 리포지토리 인터페이스 정의가 있는 경우 @EnableJpaRepository 및 해당 유형의 안전 basePackageClass=MyRepository.class 매개 변수를 사용하여 대체 패키지를 지정할 수 있습니다.
실행
이제 실행 해보겠습니다!
예상한 출력이 맞는지 한번 확인해보세요!
우리는 list를 출력하고 id가 1인 레코드을 출력하고 성이 Bauer인 사람을 찾는 코드를 작성했습니다.
네, 내부망이라서 뭐가 안됩니다...
외부망으로 돌리시고 다시 >gradlew bootrun
초기에 그래들 설정과 부팅하는데 시간이 걸릴 수 있습니다!
성공적으로 실행이 완료 되었습니다!
의문점 --해결
이번 가이드를 따라 가면서 가장 큰 의문은 실제로 관계형 데이터 베이스와 데이터를 주고 받는 것은 무엇인가 였습니다. JPA에 대한 개념도 흔들리고, work flow, dialect는 또 무엇인지 한가지 개념이 흔들리니 여러 가지 정의가 흔들렸습니다. 그렇기 때문에 개념과 정의를 확립하는데 도움이 된 post를 공유하려 합니다.
JPA 개념 및 설명
https://ggomi.github.io/JPA-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EC%84%A4%EB%AA%85/
JPA 개념 및 설명
SpringBoot와 JPA를 사용하면서 제대로 된 이해도가 낮다고 생각해서 JPA의 개념에 대해서 공부해보고, 끄적여보았습니다.. 틀린 점이나 이상한 점 있으시면 조언해주시면 감사드리겠습니다. 객체지향적 개발 vs SQL 매핑처음 Java라는 객체지향언어를 처음 배우고, 웹에 관심을 가지게 되면서 MVC 같은 디자인패턴도 배우고, 구조적인 부분이나 개
ggomi.github.io
JPA, Hibernate, Spring JPA의 차이점
https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/
JPA, Hibernate, 그리고 Spring Data JPA의 차이점
개요 Spring 프레임워크는 어플리케이션을 개발할 때 필요한 수많은 강력하고 편리한 기능을 제공해준다. 하지만 많은 기술이 존재하는 만큼 Spring 프레임워크를 처음 사용하는 사람이 Spring 프레임워크에 대한 정확한 이해를 하기는 매우 어렵다. 내가 특히 오랜 기간동안 혼란스러워했던 부분은 JPA와 관련된 개념이었다. JPA 관련 서적을 읽을 때에는 분명 EntityManager를 통해 entity CRUD를 했는데, 실제 어플리케이션 코드를 보니
suhwan.dev
Dialect(방언)이란?
https://dololak.tistory.com/465
[JPA - Hibernate] Dialect(방언)이란? 하이버네이트 Dialect 종류
Dialect(방언)이란? 표준 ANSI SQL과 방언 SQL SQL은 다음과 같이 표준 SQL인 ANSI SQL이 있으며, ANSI SQL 이외에 각 DBMS Vendor(벤더, 공급업체)인 MS-SQL, Oracle, MySQL, PostgreSQL 에서 자신만의 기능을 추..
dololak.tistory.com
JPA 쿼리문을 사용할 수는 없을까?
http://www.chidoo.me/index.php/2016/05/08/spring-data-jpa-for-short-memories/
Spring Data JPA를 활용한 DAO를 바꿔보자.
부트 이전에 스프링에서 데이터베이스를 그래도 다른 사람이 쓰는 만큼 쓸려면 MyBatis를 써줘야했다. MyBatis를 한번이라도 써본 사람이라면 알겠지만 복잡하다. 스프링 XML 설정의 복잡도에 MyBatis의 복잡도를 더하면 상당히 헬 수준으로 올라간다. 단순 목록 하나만 가져오는데 MyBatis를 쓰는건 형식주의에 빠진 불합리의 최상급이었다. 되…
www.chidoo.me
http://www.devkuma.com/books/pages/566
프로그램 개발 지식 공유, devkuma
데브쿠마는 프로그래밍 개발에 대한 지식을 공유합니다.
www.devkuma.com
'IT > Back-end' 카테고리의 다른 글
서버 기동시 port 중복 해결방법! (2) | 2020.03.18 |
---|---|
REST 방식으로 JPA Data에 접근하기 (0) | 2020.03.10 |
RESTful 웹 서비스 사용하기 -(2) (0) | 2020.03.04 |
RESTful Web Service 구축하기! (feat. spring)-(2) (0) | 2020.03.03 |
RESTful Web Service 구축하기! (feat. spring)-(1) (0) | 2020.03.03 |