[새싹 x 코딩온] 웹 풀스택 영등포 5기 21주차 회고 - 1

용가리🐉·2023년 12월 20일
0
post-thumbnail

📌 JDBC

Java DataBase Connnectivity
자바 언어와 DB를 연결해주는 통로로, 자바에서 데이터베이스에 접근할 수 있도록 해주는 자바 API

  • 단점 : 반복적이고 지루한 코드 작성 필요, SQL 예외 처리, 리소스 관리(연결, 문, 결과 집합 닫기 등) 등의 복잡한 작업을 직접 처리
  • 이제는 거의 사용하지 않는 기술

📣 Spring JDBC

JDBC의 복잡성을 줄이기 위한 Spring 프레임워크의 일부

  • 데이터베이스의 작업을 단순화하고 코드의 양을 줄여줌
  • 기존 JDBC 코드의 많은 부분을 추상화하고, 템플릿 디자인 패턴을 이용

📌 SQL Mapper와 ORM

  • Spring은 대표적으로 SQL Mapper와 ORM(Object-Relational Mapping)와 같은 두 가지 유형의 데이터베이스와의 상호작용 방식이 존재
  • 공통점 : 두 방식 모두 Java 객체와 데이터베이스 간의 상호 작용

📣 차이점

🟠 SQL Mapper

  • 주요 목적 : SQL 쿼리와 Java 메서드/객체 간의 매핑을 중심으로 함
  • 개발자는 SQL 쿼리는 직접 작성하고, 해당 쿼리의 결과를 Java 객체에 매핑함
  • 동적 SQL 생성, 조건문, 반복문 등의 SQL 작성에 있어서 유연
  • SQL 쿼리의 세밀한 튜닝이 필요할 때 주로 사용
  • ex. MyBatis, JDBCTemplate

🟠 ORM (Object Relational Mapping)

  • 주요 목적 : Java 객체와 데이터베이스 테이블 간의 관계 매핑(변환)
  • Java 객체 (Entity)가 데이터베이스의 테이블과 어떻게 매핑(변환) 될지를 정의함
  • 대부분 CRUD 연산에 대한 SQL을 자동으로 생성하며, 개발자는 객체 지향적으로 데이터를 다룰 수 있게 함
  • ex. Hibernate, JPA

JDBC, SQL Mapper, ORM 혼용

  • 기본적으로는 분리해서 사용하나, 복잡한 프로그램을 다룰 때는 같이 사용하기도 한다!
  • ex. node.js에서 mysql 모듈과 sequelize를 동시에 쓰지 않음

📌 MyBatis

  • SQL Mapper로써, JDBC로 처리하는 상당 부분의 코드와 파라미터 설정 및 결과 매핑을 대신해줌
  • 객체 지향 언어인 자바와 관계형 데이터베이스 프로그래밍을 좀 더 쉽게 할 수 있도록 도와주는 프레임워크

📣 특징

  • 쉬운 접근성과 코드의 간결함
    • JDBC의 모든 기능을 MyBatis에서 사용 가능
    • 복잡한 JDBC 코드를 걷어내 깔끔한 소스코드 유지 가능
  • SQL 문과 프로그래밍 코드의 분리
    • SQL 문과 프로그래밍 코드가 분리되어 있어 SQL에 변경이 있을 때 다시 컴파일할 필요가 없음
  • 다양한 프로그래밍 언어로 구현 가능 (Java, C#, .NET, Ruby)

📌 MyBatis 사용하기

📣 시작하기

  • build.gradle 수정
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.2'
runtimeOnly 'com.mysql:mysql-connector-j'
  • MyBatis를 사용하기 위해 dependency(라이브러리) 추가

📣 흐름

📣 application.preperties 수정

  • application.properties : 런타임 시 다양한 환경에서 동작할 수 있도록 필요한 옵션들을 제공하는데 사용되는 파일
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:포트번호/데베명?useUnicode=yes&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Seoul
spring.datasource.username=유저이름
spring.datasource.password=데베비번

mybatis.type-aliases-package=com.spring.boot.mapper
mybatis.mapper-locations=mybatis-mapper/*.xml

MyBatis 예시 코드 in GitHub

📣 MyBatis 동작 원리

  • 애플리케이션 시작 시 SqlSessionFactoryBuilder가 설정 파일을 참고해 SqlSessionFactory 생성
    • SqlSessionFactory : 데이터베이스와의 연결과 SQL의 실행에 대한 모든 것을 가진 중요한 객체
  • DB 작업 시 SqlSessionFactory가 SqlSession 생성
    • SqlSession : Connection을 생성하거나 원하는 SQL을 전달하고, 결과를 Return 해주는 객체
  • 생성된 SqlSession을 참고해 mapper 인터페이스 호출
  • Mapper가 SqlSession을 호출해 SQL 실행 후 결과 Return

📌 JPA

Java Persistence API

  • 자바 진영의 ORM 기술 표준
  • JPA가 개발자 대신 적합한 SQL을 생성하여 DB에 전달하고, 객체를 자동으로 Mapping 해주기에 SQL을 직접 작성할 필요가 없음
  • ex. Hibernate (JPA를 구현한 대표적 오픈소스)

📣 JPA 장단점

🟠 장점

  • 생산성이 뛰어나고 유지보수가 용이함
    • 기존의 SQL이 DB에 집중한 것이었다면, JPA는 객체에 집중함
  • DBMS에 대한 종속성이 줄어듦

🟠 단점

  • JPA의 장점을 살려 잘 사용하기 위해서는 학습 비용이 높고, 복잡한 쿼리를 사용할 때 불리함
    • 해당 경우에 SQL Mapper와 함께 사용
  • 잘못 사용할 경우 SQL을 직접 사용하는 것보다 성능이 떨어질 수 있음

📌 JPA 사용하기

📣 build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  • JPA를 사용하기 위해 dependency(라이브러리) 추가

📣 application.preperties 수정

# mysql connect
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

# DB function use
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
# none: not create / create: auto create / update: only update structure

logging.level.org.hibernate=info

spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql=true

📣 Entity 란?

  • 데이터베이스에 쓰일 필드와 여러 Entity 간의 관계를 설정하는 것
  • @Entity를 이용해 해당 클래스가 Entity임을 알려주고, JPA에 정의된 필드를 바탕으로 데이터베이스에 테이블을 만들 수 있음
// Entity : DB에서 쓰이는 필드와 매핑이 되는 클래스 (DB 클래스와 대응되는 클래스)

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity // 해당 클래스가 Entity 라는 것을 알려준다.
@Table(name="user2") // 테이블 이름을 명시
@Getter
@Setter
public class UserEntity {
    @Id // pk라는 것을 알려주고,
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    // 자동으로 키를 생성해주는데, 그때 사용하는 전략을 auto-increment로 하겠다.
    // (mysql 에서 가장 많이 쓰이는 방식)
    private int id;

    @Column(length = 25, nullable = false) // DB에 컬럼이다 라는 것을 알려준다.
    // name varchar(25) not null,
    private String name;

    @Column
//    @Column(columnDefinition = "TEXT")
    // nickname text
    private String nickname;


}

🟠 Entity 관련 Annotation

  • @Entity : 데이터베이스의 Table 임을 의미
  • @Table : 테이블 이름 명시
  • @Id : primary key 의미
  • @GenerateValue : primary key의 생성 전략
  • @Column : 테이블의 컬럼을 의미

📣 Repository 란?

  • Entity에 의해 생성된 DB에 접근하는 메소드를 사용하기 위한 인터페이스
  • JpaRepository를 상속받으면 기본적인 DB 접근 메소드를 사용할 수 있음
    • findAll()
    • findById()
    • findBy컬럼명()
      • findBy 뒤에는 컬럼명이 upper case로 들어와야 함
    • save()
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import sesac.mybatis.sesacmybatis.domain.User;
import sesac.mybatis.sesacmybatis.entity.UserEntity;

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

// JpaRepository<대상으로 지정할 Entity, 해당 Entity의 pk타입>
public interface UserRepository extends JpaRepository<UserEntity, Integer> {

    // findBy를 이용하고 단일값으로 받으면 ( UserEntity, Optional<UserEntity> )
    // 검색된 값이 2개 이상일 때 에러
    
//    Optional<UserEntity> findByName(String name);
    List<UserEntity> findByName(String name);
//    Optional<UserEntity> findByNickname(String nickname); // 조건에 nickname을 걸어서 실행하겠다.
    List<UserEntity> findByNickname(String nickname);

    // 아래 쿼리는 findBy 뒤에 컬럼명이 upper case로 된 형태로 들어오지 않을 때(JPA 규칙에 어긋남) 실행되는 것
    // 즉, 쿼리 어노테이션 + JPA 규칙을 동시에 한다면 쿼리가 2개가 되는 것
//    @Query("select u from UserEntity u where u.name=:name and u.nickname=:nickname")
//    @Query(nativeQuery = true, value="select * from user where name=:name and nickname=:nickname")
//    Optional<UserEntity> findByNameAndNickname(String name, String nickname);
    List<UserEntity> findByNameAndNickname(String name, String nickname);

    List<UserEntity> findByNameOrNickname(String name, String nickname);

//    @Query(nativeQuery = true, value="select * from user2 where name=:name")
//    UserEntity findExist(String name);
    // JPA 메소드 존재
    boolean existsByName(String name);
}

📣 Optional 란?

  • null 일 수도 있는 객체를 감싸는 Wrapper 클래스
  • Optional<T> option
    • Option 변수 내부에는 null이 아닌 T 객체가 있을 수도 있고 null이 있을 수도 있음
    • 즉, Optional 클래스는 여러 가지 API를 제공해 null일 수도 아닐 수도 있는 객체를 다룰 수 있음

JPA 예시 코드 in GitHub

profile
자아를 찾아 떠나는 중,,,

0개의 댓글

관련 채용 정보