-
[Spring] JDBC와 ORM SQL Mapper는 무엇이고 JPA vs MyBatis 는 뭐가 다른가?개발관련/Spring 2024. 6. 28. 03:04
JDBC / ORM / SQL Mapper 의 공통점
: 영속성(Persistence)을 가진다.
💡영속성; 데이터를 생성한 프로그램의 실행이 종료되어도 데이터가 사라지지 않는 데이터 또는 영구히 저장되는 특성을 말한다.
위의 두 그림은 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 JDBCJPA
HIBERNATE
Spring Data JDBC / Spring Data JPA1. JDBC 란?
: 여러 DB 제품군에 따른 Driver를 만들어 우리가 사용하는 API를 변경하지 않고 Driver Manager만 바꿔 DB의 확장성을 높인 기술이다.
[JDBC- 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]
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
- Spring Data 진영에서 만든 JPA
- Core Concept로 Repository를 제안
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