ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] JDBC와 ORM SQL Mapper는 무엇이고 JPA vs MyBatis 는 뭐가 다른가?
    개발관련/Spring 2024. 6. 28. 03:04

    JDBC / ORM / SQL Mapper 의 공통점

    : 영속성(Persistence)을 가진다.

    💡영속성; 데이터를 생성한 프로그램의 실행이 종료되어도 데이터가 사라지지 않는 데이터 또는 영구히 저장되는 특성을 말한다.

    layered-architecture 90's
    layered-architecture early 2000's

     

    위의 두 그림은 DB 접근이 일어나는 순서를 도식화 한 것이다. 90년대, 2000년대 초 Layered-Architecture이다.

    DB접근은 Domain Model 단계에서 일어나게 되는데 DB와 연동을 위해 데이터 영속성이 반드시 필요하다.

     

    #부연설명
    애플리케이션의 실행시 프로세스 휘발성 메모리인 LAM위에 올려 실행하게 된다.

    그런데 만약 프로세스가 예기치 않게 종료되더라도 프로세스 실행 중 들어온 데이터에서 유저 데이터 같이 몇가지의 데이터는 특별히 보존해야 할 필요가 있다. DB에 데이터를 저장하기 위한 JDBC / ORM / SQL Mapper 에 대해 알아보려 한다.

     


    JDBC / SQL Mapper / ORM 에 해당하는 기술들

    JDBC SQL Mapper ORM
    JDBC API MyBatis
    Spring JDBC
    JPA
    HIBERNATE
    Spring Data JDBC / Spring Data JPA

     

    1. JDBC 란?

    : 여러 DB 제품군에 따른 Driver를 만들어 우리가 사용하는 API를 변경하지 않고 Driver Manager만 바꿔 DB의 확장성을 높인 기술이다.

     

     

    [JDBC- JDBC API]

    JDBC API 도식화

     

    JDBC 사용순서 (DriverManager -> Connection -> Statement -> ResultSet)

    (a). Driver Manager를 이용해 Connection 인스턴스를 얻는다.

    (b). Connection을 통해서 Statement를 얻는다.

    (c). Statement를 이용해 ResultSet을 얻는다.

     

    JDBC 불편사항

    - 코드 중복이 많다.

    - 지속적인 Connection 관리 필요

    ❗️JDBC 개선 사항으로 SQL Mapper 등장!

     


    2. SQL Mapper 란?

    [SQL Mapper - Spring JDBC]

    SQL Mapper - Spring JDBC 도식화

    public class CrewDAO{
      private JdbcTemplate jdbcTemplate;
     
      @Autowired
      public void setDataSource(DataSource dataSource){
        this.jdbcTemplate = new JdbcTemplate(dataSource);
      }
     
      public List<Crew> getCrews(){
        return jdbcTemplate.query("select * from crews", new RowMapper<Crew>(){
          @Override
          public Crew mapRow(ResultSet rs, int rowNum) throws SQLException{
            return new Crew(rs.getInt("id"), rs.getString("name"));
          }
        });
      }
    }
    
    // 코드 출처 : JDBC, SQLMapper, ORM 비교
    // https://sdesigner.tistory.com/101

     

    Connection에 대한 Configuration을 JdbcTemplate라는 클래스에 담아 Spring 을 통해 주입 받는다.

    Method에 쿼리를 매핑해두고 RowMapper를 통해 쿼리 Method를 호출, 결과를 통해 DB의 각 row마다 하나의 인스턴스화를 지원해준다. 추상화가 많이 이루어져 이전보다 편하게 사용할 수 있다.

     

    동작 Spring 개발자
    연결 파라미터 정의   ⭕️
    연결 오픈 ⭕️  
    SQL문 지정   ⭕️
    파라미터 선언 & 값 제공   ⭕️
    Statement 준비와 실행 ⭕️  
    (존재시)
    결과를 반복하는 루프 설정
    ⭕️  
    각 iteration에 대한 작업 수행   ⭕️
    모든 예외 처리 ⭕️  
    트랜잭션 제어 ⭕️  
    연결, Statement, ResultSet 닫기 ⭕️  

    개발자가 사용할 DB에 대한 연결 파라미터를 넣어주면 Spring이 알아서 연결을 열어준다.

    + 개발자가 원하는 쿼리를 설정, 해당 쿼리에 들어가는 파라미터를 넣어주면 Spring이 해당 statement를 알아서 수행해준다.

    + 결과 ResultSet에 대한 루프, 예외처리, 트랜잭션, 종료 까지 많은 부분을 대신처리 해주어 불편함을 덜어줬다.

     

     

    [SQL Mapper - MyBatis]

    Mybatis는 기존 JDBC 문제점을 Spring JDBC와 약간 다르게 해석했다.

    Java 코드에서 SQL을 쓰는 것 자체를 분리하는 것을 목표로 잡았다.

    Query를 Java에서 XML로 이동하는 것!

     

    • 복잡한 JDBC 코드 ❌
    • ResultSet과 같이 결과값을 매핑하는 객체 ❌
    • 간단한 설정 ⭕️
    • 관심사 분리 ⭕️

     

    DAO 세팅

    public interface CrewDAO{
      public List<Crew> selectAll();	// 모든 행 가져오기
      public Crew selectById(int id);	// 특정한 행 가져오기
      public int insert(Crew crew);		// 삽입
      public void update(Crew crew);	// 업데이트
      public void delete(int id);		// 삭제
    }
    
    // 코드 출처 : JDBC, SQLMapper, ORM 비교
    // https://sdesigner.tistory.com/101

     

    Mapper XML 세팅

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.dao.CrewDao">
        <resultMap id="result" type="Crew">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
      </resultMap>
     
      <select id="selectAll" resultType="result">
            SELECT * FROM crews;
      </select>
     
      <select id="selectById" parameterType="int" resultType="result">
            SELECT * FROM crews WHERE id = #{id};
      </select>
     
      <insert id="insert" parameterType="Crew" useGeneratorKeys="true" keyProperty="list_id">
        INSERT INTO crews(name) VALUES(#{name});
      </insert>
     
      <update id="update" parameterType="Crew">
        UPDATE crews SET name = #{name} WHERE id = #{id};
      </update>
     
      <delete id="delete" parameterType="int">
        DELETE from crews WHERE id =#{id}
      </delete>
    </mapper>
    
    // 코드 출처 : JDBC, SQLMapper, ORM 비교
    // https://sdesigner.tistory.com/101

     

    Mapper를 호출하는 Mybatis Session (CRUD Query에 파라미터 주입하여 쿼리 결과 조회)

    public class Main{
      public static void main(String[] args){
        // Mybatis 세션 연결
        SqlSession sqlSession = MtBatisconnectionFactory.getSqlSessionFactory()
          .openSession(true);
     
        // Mapper 연결
        CrewDao crewDao = sqlSession.getMapper(CrewDAO.class);
     
        // Select
        List<Crew> crews = crewDao.selectAll();
        for(int i = 0; i < crews.size(); i++){
          System.out.println("크루 이름: "+crews.get(i).getName());
        }
        // Insert
        Crew kouz = new Crew();
        kouz.setName("코즈");
        crewDao.insert(kouz);
     
        // Update
        kouz.setName("코우우우즈");
        crewDao.update(kouz);
     
        // Delete
        crewDao.delete(kouz.getId());
      }
    }
    
    // 코드 출처 : JDBC, SQLMapper, ORM 비교
    // https://sdesigner.tistory.com/101

     

     

    3. ORM 이란?

    ORM(Object Relational Mapping)을 의미한다.

    즉, 객체(Object)와 DB상의 테이블을 연결(Mapping)시켜 RDB 테이블을 객체지향적으로 사용하게 해주는 기술이다.

     

    [ORM - JPA(Java Persistence API) / Hibernate]

    객체지향적으로 구현되어 있는 구조에서 RDBMS와 간편하게 연결하기위한 기술이다.

    // A 코드
    public class Crew{
      private int id;
      private String name;
    }
    
    // B 코드
    public class Crew{
      private int id;
      private String name;
      private String nickName;
    }
    
    // 코드 출처 : JDBC, SQLMapper, ORM 비교
    // https://sdesigner.tistory.com/101

     A코드 구조에서 B코드 구조로 변경된다면, SQL구문도 이에 맞춰 변경해줘야 한다.

     

    String sql = "INSERT INTO CREW(CREW_ID, NAME, NICKNAME) VALUES(?,?,?)";
    ...
      pstmt.setString(3, crew.getNickName());
    ...
     
    ...
      SELECT CREW_ID, NAME, NICKNAME FROM CREW WHERE CREW_ID = ?
    ...
    
    // 코드 출처 : JDBC, SQLMapper, ORM 비교
    // https://sdesigner.tistory.com/101

     

    "물리적으로 SQL과 JDBC API를 데이터 접근 계층에 숨기는데 성공했을지는 몰라도,

    논리적으로는 엔티티와 아주 강한 의존 관계를 가지고 있다."

    - 김영한님의 Spring

     

     

    관계형데이터베이스에서는 객체지향에서의 개념인 연관관계(객체 참조), 상속을 그대로 표현하는 것이 어렵고 불편한 문제가 있었다.

    객체 지향과 관계형데이터베이스의 시작점, 설계원칙이 다름 -> 패러다임의 불일치 -> 개발자들의 SQL 의존적인 구현 현상 발생

    이를 해결하기 위해 JPA가 등장함.

    JPA는 표준 인터페이스가 있고, 이를 구현하는 실제 서비스가 여러가지 존재한다. 그 중 하나가 Hibernate이고, 그 외 다양하게 존재한다. JPA도 JDBC API가 여러 Driver를 변경할 수 있던 것처럼 마찬가지로 추상화를 통해 손쉽게 기술 변경이 가능하다.

     

    [ORM - Spring Data JPA / Spring Data JDBC]

    Spring Data JPA의 DB 접근방법

     

    Spring Data JPA

    • Spring Data 진영에서 만든 JPA
    • Core Concept로 Repository를 제안

     

    Spring Data JDBC와 DB 접근방법

     

    Spring Data JDBC

    • Core Concept : Simple

    객체지향으로 설계된 프로그램에서 DB에 접근하다보니 많은 기술들이 사용됐다.

    이에 DDD 구조로 한꺼번에 Entity를 주고 받는 방식으로 DB에 접근하는 방법을 고안해냈다.

     

    Spring Data JDBC는 위 사진처럼 Hibernate와 같은 기술을 사용하지 않고 JDBC API를 그대로 직접 구현해서 사용하는 방식으로 동작된다. 물론 Spring Data 이므로 Repository 개념은 그대로 갖고 있다.


     

    [JPA 와 MyBatis 차이]

     

    > SQL Mapper
    ; Object와 SQL의 필드를 매핑하여 데이터를 객체화 하는 기술

    • 객체와 테이블 간의 관계를 매핑하는 것이 아님
    • SQL문을 직접 작성하고 쿼리 수행 결과를 어떠한 객체에 매핑할지 바인딩 하는 방법
    • DBMS에 종속적인 문제
    • EX) JdbcTemplate, MyBatis

    > ORM
    ; Object와 DB테이블을 매핑하여 데이터를 객체화하는 기술

    • 개발자가 반복적인 SQL을 직접 작성하지 않음
    • DBMS에 종속적이지 않음
    • 복잡한 쿼리의 경우 JPQL을 사용하거나 SQL Mapper을 혼용하여 사용 가능

    > JPA(ORM)
    JPA : ORM(Object Relational Mapping) 기술

    • 자바 ORM의 기술 표준
    • 대표적인 오픈소스로 Hibernate
    • CRUD 메소드 기본 제공
    • 쿼리를 만들지 않아도 됨
    • 1차 캐싱, 쓰기지연, 변경감지, 지연로딩 제공
    • MyBatis는 쿼리가 수정되어 데이터 정보가 바뀌면 그에 사용 되고 있던 DTO와 함께 수정해주어야 하는 반면에, JPA 는 객체만 바꾸면 된다.
    • 즉, 객체 중심으로 개발 가능
    • but 복잡한 쿼리는 해결이 어려움

     

    > MyBatis(SQL Mapper)
    MyBatis : Object Mapping 기술

    • 자바에서 SQL Mapper를 지원해주는 프레임워크
    • SQL문을 이용해서 RDB에 접근, 데이터를 객체화 시켜줌
    • SQL을 직접 작성하여 쿼리 수행 결과를 객체와 매핑
    • 쿼리문을 xml로 분리 가능
    • 복잡한 쿼리문 작성 가능
    • 데이터 캐싱 기능으로 성능 향상
    • but 객체와 쿼리문 모두 관리해야함, CRUD 메소드를 직접 다 구현해야함.

    참조 : https://sdesigner.tistory.com/101

    https://velog.io/@rladuswl/ORM의-개념-JPA와-MyBatis-차이https://mangkyu.tistory.com/20?category=872426

    https://mangkyu.tistory.com/20?category=872426

Designed by Tistory.