본문 바로가기
Spring, Springboot

5월 8일자 수업 Spring Boot 스프링 JPA <chapter03 >

by jyee 2023. 5. 8.
728x90
반응형

 

스프링 JPA(Java Persistence API)

- 스프링에서 데이터를 처리할 수 있도록 돕는 라이브러리이다

- 데이터베이스에 종속적인 SQL문 없이도 개발이 가능하기 때문에 개발의 생산성을 높일 수 있다

- 기존의 JDBC 등을 이용해서 직접 구현했던 데이터베이스 관련 작업을 대신 처리해주는 추상화된 계층의 구현 스펙이다

 

- 스프링 데이터 JPA를 사용하는 경우는 별도의 구현 클래스를 만들지 않고 인터페이스만 정의함으로써 기능을 사용할 수 있다.

- 스프링 부트가 내부적으로 인터페이스에 대한 구현 객체를 자동으로 생성해준다.

 

JPA란?

JPA란 Java Persistence API의 약자이며 자바의 ORM을 위한 표준 기술로 Hibernate, Spring JPA, EcliplseLink 등 과 같은 구현체가 있고 이것의 표준 인터페이스가 JPA 입니다.

ORM(Object-Relational Mapping)이란 자바의 객체와 관계형 DB를 맵핑하는 것으로 DB의 특정 테이블이 자바의 객체로 맵핑되어 SQL문을 일일이 작성하지 않고 객체로 구현할 수 있도록 하는 프레임워크입니다.

JPA의 장점으로, SQL 위주의 Mybatis 프로젝트와 비교하여 쿼리를 하나하나 작성할 필요도 없어 코드량이 엄청나게 줄어듭니다. 또한 객체 위주로 코드가 작성되다 보니 가독성도 좋고, 여러 가지 요구사항으로 기능 수정이 발생해도 DB부터 더 간편하게 수정이 가능합니다. 또한 Oracle, MySQL 등 DB 벤더에 따라 조금씩 다른 SQL 문법 때문에 애플리케이션이 DB에 종속될 수밖에 없었는데, JPA는 직접 쿼리를 작성하는 것이 아니라서 DB 벤더에 독립적으로 개발이 가능합니다.

 

오늘 수업 실습 Chapter03_JPA 참고 

 

하나씩 차례대로 완성하기

1.pom.xml 
2.application.properties / application.yml 
3.BoardDTO.java 

 

 

======== 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>3.0.6</version>

<relativePath/> <!-- lookup parent from repository -->

</parent>

<groupId>com.example</groupId>

<artifactId>Chapter03_JPA</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>Chapter03_JPA</name>

<description>Demo project for Spring Boot</description>

<properties>

<java.version>17</java.version>

</properties>

<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-devtools</artifactId>

<scope>runtime</scope>

<optional>true</optional>

</dependency>

 

<dependency>

<groupId>com.mysql</groupId>

<artifactId>mysql-connector-j</artifactId>

<scope>runtime</scope>

</dependency>

 

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<optional>true</optional>

</dependency>

 

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

</dependencies>

 

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

<excludes>

<exclude>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</exclude>

</excludes>

</configuration>

</plugin>

</plugins>

</build>

 

</project>

 

 

 

 

 

 

========= appliction.properties / application.yml =========

#Server Port

server.address=localhost

server.port=8080

 

 

#MySQL

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

spring.datasource.url=jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Seoul

spring.datasource.username=root

spring.datasource.password=1234

 

 

 

#JPA

#스키마 생성, create: 기존 테이블이 있으면 삭제 후 생성 그래서 데이터가 안 쌓임 , update: 변경된 부분만 반영

spring.jpa.hibernate.ddl-auto=update

 

 

# DDL 생성 시 데이터베이스 고유의 기능을 사용하는가?

spring.jpa.generate-ddl=true

 

 

#api 호출 시 실행되는 sql문을 콘솔에 보여 줄 것인가?

spring.jpa.show-sql=true

 

 

#사용할 데이터베이스

spring.jpa.database=mysql

 

#mysql 상세 지정

spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect

 ========================================

 

 =========BoardDTO============

package com.example.demo;

 

 

import java.sql.Timestamp;

 

import org.hibernate.annotations.CreationTimestamp;

 

import jakarta.persistence.Column;

import jakarta.persistence.Entity;

import jakarta.persistence.GeneratedValue;

import jakarta.persistence.GenerationType;

import jakarta.persistence.Id;

import jakarta.persistence.SequenceGenerator;

import jakarta.persistence.Table;

import lombok.Data;

 

 

@Entity

@Table(name="board")

@Data

@SequenceGenerator(name = "BOARD_SEQ_GENERATOR",

sequenceName = "BOARD_SEQ",

initialValue = 1,

allocationSize = 1)// 1로 시작해서 1씩 증가 한다는 것

public class BoardDTO {

 

@Id

@Column(name = "seq")

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BOARD_SEQ_GENERATOR")

private int seq;

 

//@Id //이게 primary key라는 걸 알려줌

@Column(name="id", nullable= false, unique = true, length = 30)

private String id;

 

@Column(name="name", nullable= false, length = 30)

private String name;

 

@Column(name = "subject")

private String subject;

 

@Column(name = "content")

private String content;

 

@CreationTimestamp // 엔티티가 생성되는 시점의 시간 등록

private Timestamp logtime;

 

 

}

 

코드 부연 설명:

BoardDTO 클래스는 @Entity 어노테이션을 통해 JPA 엔티티임을 나타내고, @Table 어노테이션을 통해 이 엔티티를 저장할 데이터베이스 테이블의 이름을 지정합니다.

 

클래스 내에는 게시판 정보를 담는 필드들이 정의되어 있습니다. 각 필드는 @Column 어노테이션을 사용하여 데이터베이스 컬럼과 매핑되도록 설정되어 있습니다.

  • @Id 어노테이션을 사용하여 primary key를 나타내는 seq 필드가 정의되어 있습니다.
  • @SequenceGenerator 어노테이션을 사용하여 BOARD_SEQ_GENERATOR라는 이름으로 시퀀스 생성기를 등록하고, 이를 seq 필드에 적용하여 게시글이 추가될 때마다 seq 필드 값이 1씩 증가하도록 설정되어 있습니다.
  • id, name, subject, content 필드는 각각 게시글 작성자, 작성자 이름, 제목, 내용을 나타내며, nullable, unique, length 등의 속성이 지정되어 있습니다.
  • @CreationTimestamp 어노테이션을 사용하여 logtime 필드가 엔티티가 생성된 시간으로 자동으로 설정되도록 지정되어 있습니다.

마지막으로, Lombok의 @Data 어노테이션을 사용하여 자동으로 getter/setter 메소드와 equals, hashCode, toString 등의 메소드가 생성되도록 설정되어 있습니다.

 

@Entity

JPA에서는 엔티티는 테이블에 대응하는 하나의 클래스라고 생각하면 된다

spring-boot-starter-data-jpa 의존성을 추가하고 @Entity 어노테이션을 붙이면 테이블과 자바 클래스가 매핑이 된다.

 

 

 

Spring Boot + MySQL + JPA

스프링 데이터 JPA를 사용하는 경우는 별도의 구현 클래스를 만들지 않고 인터페이스만 정의함으로써 기능을 사용할 수 있다. 스프링 부트가 내부적으로 인터페이스에 대한 구현 객체를 자동으로 생성해준다.

또한 JPA를 이용해서 데이터베이스를 연동하기 위해서 사용했었던 EntityManagerFactory,

EntityManager, EntityTransaction 같은 객체도 필요 없다.

이 모든 객체들의 생성과 활용이 스프링 데이터 JPA 에서는 내부적으로 처리되기 때문이다.

 

 

파일 만들기~~!!


BoardController.java

Interface: BoardService.java
Class: BoardServiceImpl.java

Interface: BoardDAO.java

 

 

 

 ==========BoardController.java ===========

package com.example.demo;

 

import java.util.List;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

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

 

@RestController

public class BoardController {

 

@Autowired

private BoardService boardService;

 

@GetMapping(value = "/board/write")

public String write() {

 

boardService.write();

return "게시판 등록 성공"; //문자열을 브라우저에 뿌린다.

}

 

@GetMapping(value = "/board/getBoardList")

public List<BoardDTO> getBoardList() {

List<BoardDTO> list = boardService.getBoardList();

return list;

 

}

}

 

코드 부연 설명: 

REST API를 처리하는 컨트롤러는 웹 애플리케이션에서 클라이언트와 서버 사이의 통신을 담당하는 클래스이다. 이 컨트롤러는 클라이언트로 부터 HTTP요청을 받아 해당 요청에 대한 응답을 반환하며, RESTful API 디자인 규칙을 따라 요청 URL과 HTTP 메소드를 기반으로 적절한 기능을 수행합니다. 일반적으로 스프링 프레임워크에서는 @RestController 어노테이션을 사용하여 REST API를 처리하는 컨트롤러를 정의합니다.

 

파일 흐름도~~

1번 controller 

2번 serviceImpl

3번 boardDAO

 

 

 

========================BoardServiceImpl =======================

package com.example.demo;

 

import java.util.List;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

@Service

public class BoardServiceImpl implements BoardService {

 

@Autowired

private BoardDAO boardDAO;

 

@Override

public void write() {

BoardDTO boardDTO = new BoardDTO();

boardDTO.setId("hong");

boardDTO.setName("허균");

boardDTO.setSubject("홍길동전");

boardDTO.setContent("불쌍한 사람들을 도와주는 의적!");

 

boardDAO.save(boardDTO);

 

 

boardDTO = new BoardDTO();

boardDTO.setId("doori");

boardDTO.setName("김수정");

boardDTO.setSubject("아기공룡 둘리");

boardDTO.setContent("빙하타고 내려온 아기공룡");

 

boardDAO.save(boardDTO);

 

}

 

@Override

public List<BoardDTO> getBoardList() {

return boardDAO.findAll();

}

 

}

=====================================

 

 

==============BoardDAO================

package com.example.demo;

 

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

import org.springframework.stereotype.Repository;

 

@Repository

//public interface BoardDAO extends JpaRepository<BoardDTO, String>{

public interface BoardDAO extends JpaRepository<BoardDTO, Integer>{

 

}

 

 

 

/*

JpaRepository<BoardDTO, ID>

JpaRepository<엔티티 클래스, primary key의 타입(자료형)을 쓴다.>{

 

*/

 

 

===================================================

BoardDAO 코드 부연 설명 : 

JpaRepository<BoardDTO, ID>

JpaRepository<엔티티 클래스, primary key의 타입(자료형)을 쓴다.>{

이 부분을 추가 설명하자면  BoardDTO에서 어떤게 @ID 즉, primary key인지 보고 그에 맞게 자료형을 쓰는거이다. 

먼저 주석 처리가 된  String에서는 기존 @ID 가 name="id"였었기에 String  타입으로 했던거였고 

추후에는 int seq가 @ID로 걸렸기에 자료형이 Integer인것! 

728x90
반응형