study

(230614) JPA

hjkeeeem 2024. 9. 3. 01:44

IoC Container

Spring에는 Bean 객체로 등록하기 위한 annotation이 다양하게 존재한다.

Ex) Controller, Component, Service, Repository ... 

이러한 어노테이션들이 저장된 패키지 => org.springframework.stereotype

이러한 어노테이션을 bean객체로 사용 시 ioc 관리 하에 사용되게 될 것이다.

 

Stereotype

구현된 기능상의 차이도 있지만 주된 목적은 역할의 표시이다.

- 해당 클래스가 어떤 역할을 하는지 

- 어노테이션 기반 관점 지향 프로그래밍

- 실제 구현보다 역할적인 구분에 초점이 맞춰져 있다.

 

@Component

가장 기초가 되는 Annotation으로 @ComponentScan의 대상이다.

- 직접적인 비즈니스 로직에서 벗어난 기능들 

- 외부 API, 다수 구성 요소의 공유 가능 기능 등

- 또는 다른 Annotation을 쓰기 애매할 때 사용

 

 

@Service

서비스의 주요 흐름 , 비지니스 로직을 담당하는 요소

- 여러 요소들의 기능을 조합해 실제 서비스를 제공하기 위한 주요 기능 담당

- Controller로 부터 입력을 받고

- Repository로 부터 데이터를 받고

- 이를 바탕으로 결정을 전달

 

Service에서 서비스를 제공하기 위해 작성하는 비지니스 로직에 필요한 데이터를 Repository에서 받아오는건가요?

때문에 Service에서 사용하기 때문에 Service 클래스에서 repository에 대한 생성자를 생성해주고,

Controller는 Service에서 만든 로직을 사용하여 view에 띄운다던가 어떠한 처리를 위해 Controller 클래스에서 service 생성자 생성

 

 

@Repositorty

데이터베이스와의 소통을 담당

 

 

@Controller

MVC 패턴의 Controller , 즉 사용자 입력 담당 요소

- 주로 @RequestMapping과 함께 사용 

 

 

@ResponseBody & RestController

Q. @Controller는 html만 반환하는가?

A. 위 사진의 20번째 줄 home에 노란줄이 쳐져있는 이유는 resorces > static 혹은 templates 안에 html파일이 존재하지 않기 때문에

     반환할 html 파일이 없다. 라는 것을 의미한다.

     하지만 @ResponseBody 어노테이션을 붙이게 되면 노란줄이 사라지게 되는데, 이는 위 사진의 주석과 같이 전달하고자 하는 것이 꼭

     html이 아니다. 라는 뜻을 내포하고 있는 어노테이션이다.

 

Q. 그러면 사용하는 모든 메서드에 @ResponseBody를 붙여야 할까?

A. 아니다. @RestController 사용 시 자동으로 모든 메서드에 @RespneseBody를 붙여준다.

 

 

MVC 설명 요약

 

 

 

JPA 

데이터베이스 객체를 표현 하기 어렵다.에서 시작된 JPA의 ORM 개념

 

문제들

우리가 사용하는 언어는 객체지향 프로그래밍 언어

- 객체와 객체가 상호작용한다.

- 또는 하나의 객체가 다른 객체를 소유한다. 

FoodObject 는 OrderObject의 소유가 된다.

 

 

관계형 데이터베이스에서는?

- 한 컬럼에 다른 객체에 대한 정보를 직접 다룰 수 없음

- 조회 후 별도로 Join이 필요

 

 

Object Relational Mapping

- 객체 지향적 관점에서 객체를 사용하여 관계형 데이터베이스를 사용하는 기술

- 객체 테이블 및 레코드에 매핑

- 실제 SQL을 작성하지 않고 위임(객체 생성 시 테이블이 자동으로 생성)하기 때문에 성능에 영향이 없지 않다.

==> 생산성 증가, 중복 감소, 데이터베이스 의존성 감소 

 

 

JPA와 Hibernate

JPA (Java Persistence API)

- 데이터가 어떻게 테이블에 매핑되는지 명세하기 위함

- 인터페이스와 어노테이션으로 구성

@Entity 어노테이션을 붙일 시 hibernate가 Entity가 붙은 모든 객체들을 확인해서 테이블의 형태로 데이터베이스에 생성해줌.

실제로 테이블로 옮겨주는 역할은 hibernate framework (orm 적용)

 

 

 

@Entity 어노테이션을 붙일 시 public class StudentEntity 클래스 객체를 테이블로 생성해준다.

@Id, @GeneratedValue를 붙이지 않았을 때는 클래스명에 빨간줄 오류가 생기는데 이것은 기본키를 지정해주지 않아 나타나는 오류

 

실행 시 콘솔창에 hibernate가 자동으로 테이블명을 지정하여 StudentEntity 클래스 안에 있는 변수를 column으로 적용하여 

student_entity라는 이름의 테이블명이 생성되었다는 문구가 뜨며 실제 db.sqlite를 확인해보아도 테이블이 생성된 것을 확인할 수 있다.

 

 

테이블명 설정해주기

@Table 사용 시 테이블 명을 지정할 수 있다. 

기존에 있던 student_entity 테이블명을 변경하는 것이 아니라 지정해준 students 이름의 테이블이 '생성'된다.

 

 

 

JPA 실습 - CRUD

Create

AppService

@Service // 주된 비지니스 로직이 구현되는 공간
public class AppService {
    // Controller는 사용자에게서 들어온 요청을 해석해서 전달
    // Service : 데이터베이스 조회, 데이터 입력, component 사용, 모은 데이터를 가지고 응답 또는 의사결정

    private final AppRepository repository;
    // JpaRepository
    private final StudentRepository studentRepository;

    public AppService(AppRepository repository, StudentRepository studentRepository){ //IoC 컨테이너야 나 레포지토리 필요해
        this.repository = repository; // 내가 사용할 수 있게 준비
        this.studentRepository = studentRepository;
    }

    //CREATE
    public void createStudent(String name, Integer age, String phone, String email){
        // 새로운(new) Student(Entity)를 만들고 싶다
        StudentEntity newEntity = new StudentEntity();
        newEntity.setName(name);
        newEntity.setAge(age);
        newEntity.setPhone(phone);
        newEntity.setEmail(email);
        // repository.save 나의 reository에 저장하구 싶다.
        this.studentRepository.save(newEntity);
    }

현재 DTO가 생성되지 않았기 때문에 생성자에 사용 변수를 생성해준 것

 

 

AppController에서 실행

@RestController //api에 특화 되어있는 controller로 모든 메소드에 @ResponseBody를 붙여준다.
public class AppController {
    // 사용자의 입력을 직접 받는 요소 (나타내는)
    private final AppService service;

    public AppController(AppService service){
        this.service = service;
    }

    @GetMapping("create")
    public @ResponseBody String create(){
        this.service.createStudent("alex",35,"010-1234-5678","alex@gmail.com");
        return "done";
    }

 

 

localhost:8080/create 

 

 

Read & Read All

**

위 설정을 create로 설정했기 때문에 '새로' 테이블을 생성하기 때문에

localhost:8080/create를 한번 거친 후에 실행해야 한다.

 

**

[Read] AppService.java

public void readStudent(Long id){
        System.out.println(this.studentRepository.findById(id));
    }

[Read] AppController.java

@GetMapping("read")
    public @ResponseBody String readOne(){
        this.service.readStudent(1L);
        return "done-read-one";
    }

 

 

[ReadAll] AppService.java

public void readStudentAll(){
        System.out.println(this.studentRepository.findAll());
    }

 

[ReadAll] AppController.java

@GetMapping("read-all")
    public @ResponseBody String readAll(){
        this.service.readStudentAll();
        return "done-read-all";
    }

 

 

Update

1. 코드 작성

2. db refresh 하기 -> 데이터가 전부 없어야 함.

3. localhost:8080/create 접속 후 데이터 잘 들어갔나 확인

3. localhost:8080/update

4. alex 이름 바뀌었나 확인

 

 

Delete

 

실행 직후

 

 

create

 

 

delete