데이터들이 프로그램이 종료되어도 사라지지않고 어떤 곳에 저장되는 개념을 영속성(Persistence)이라고 한다.
Java에서는 데이터의 영속성을 위한 JDBC를 지원해주는데, 이는 매핑작업을 개발자가 일일히 수행해야 하는 번거로움이 있다.
⇒ JDBC 커넥션 방법 정리는 : JDBC와 Connection Pool
SQL Mapper와 ORM은 개발자가 직접 JDBC Programming을 하지 않도록 기능을 제공해주는 Persistence Framework 이다.
이것을 사용하는 이유는
기존 JDBC만의 사용으로는 쿼리문이 조금만 길어져도 요청하는 과정의 관리가 번거롭기 때문에,
JPA와 MyBatis 라이브러리를 사용하여 문제를 해결할 수 있기 때문이다.
Persistence Framework
1. SQL Mapper
Object와 SQL의 필드를 매핑하여 데이터를 객체화 하는 기술
[특징]
- 객체와 테이블간의 관계를 매핑하는 것이 아니라,
SQL문을 직접 작성하고 쿼리 수행결과를 어떠한 객체에 매핑할지 바인딩하는 방법이다.
- DBMS에 종속적
ex) JdbcTemplate, MyBatis
2. ORM (Object Relational Mapping)
Object와 DB테이블을 매핑하여 데이터를 객체화하는 기술
(관계형 데이터베이스를 OOP언어로 변환해주는 기술)
[특징]
- 개발자가 반복적인 SQL 쿼리문을 직접 작성하지 않음
- DBMS에 종속적이지 않음
- 복잡한 쿼리의 경우 JPQL을 사용하거나 SQL Mapper를 혼용하여 사용가능하다.
ex) JPA
[장점]
1. ORM을 사용하면서 쿼리를 가져와서 실행하고 파싱하는 과정이 없어져서 비즈니스 로직에 집중할 수 있다. 한마디로, 객체중심의 개발이 가능해진다.
2. 메소드 호출만으로도 간편하게 실행가능해서 생산성이 높아지고 유지보수가 쉬워진다.
3. DB에 의존하지 않아 다른 DB로 바꾸게 되어도 설정만 바꾸면 사용할 수 있다.
[단점]
1. 직접 SQL문을 작성하는 것보다 속도가 느려 성능이 떨어진다.
2. 복잡한 쿼리들은 Hibernate로 구현하기가 어렵다.
MyBatis와 JPA
MyBatis
Java에서 SQL Mapper를 지원해주는 프레임워크
[특징]
- XML 또는 SQL 쿼문을 이용해서 RDB에 접근하여 데이터를 객체화시켜준다.
- SQL을 직접 작성하여 쿼리 수행 결과를 객체와 매핑한다.
(객체와 테이블간의 관계를 매핑하는 것이 아니다)
- 쿼리문을 xml로 분리가 가능하다.
[장점]
1. JPA보다 복잡한 쿼리문을 작성하고 해결하는 것이 수월하다.
2. 데이터 캐싱기능으로 성능이 향상된다.
[단점]
1. 객체와 쿼리문 모두를 관리해야하고 CRUD 메소드를 직접 개발자가 다 구현해야 해 번거롭다.
JPA (Java Persistence API)
Java ORM의 표준 기술
ORM을 위해 자바에서 제공하는 API
[특징]
- 자바 객체와 DB테이블을 매핑
- 구현체로는 Hibernate 가 있다.
- JPQL(Java Persistence Query Language)을 사용하여 데이터베이스와 상호작용한다.
- CRUD 메소드를 기본적으로 제공하기 때문에 SQL 쿼리를 만들지 않아도 된다.
- 1차 캐싱, 쓰기 지연, 변경감지, 지연로딩을 제공한다.
[장점]
1. 데이터 정보가 수정되면 객체만 바꿔주면 된다는 장점이 있다.
따라서, 객체중심으로 개발이 가능해진다.
=> MyBatis와의 차이 : MyBatis는 쿼리가 수정되어 데이터 정보가 바뀌면 사용되고 있던 DTO와 함께 수정해주어야 하지만, JPA는 객체만 바꾸면된다.
2. 타입 안정성이 더 좋고 지연로딩을 통해 애플리케이션 성능을 개선할 수 있다.
3. JPA는 Java EE 명세이므로 서로 다른 애플리케이션 서버 및 환경에서도 호환성을 보장한.
[단점]
1. 복잡한 쿼리는 메소드로 처리가 어렵다.
(=> 이러한 문제는 QueryDSL 이라는 오픈소스를 사용한다면 문제를 해결할 수 있다.)
>>정리
ORM이란, 객체와 DB의 테이블을 Mapping 시켜 RDB 테이블을 객체지향적으로 사용하게 해주는 기술이다.
RDB 테이블은 객체지향적 특성(상속, 다형성, 레퍼런스)등이 없어서 Java와 같은 객체지향적 언어로의 접근이 쉽지않다. 이때, ORM을 사용하면 객체 지향적으로 RDB를 사용할 수 있다.
객체와 RDB가 별개로 설계되어있으면 중간에서 ORM이 그 둘을 매핑해주는 역할을 한다. ORM은 SQL문이 아니라 RDB의 데이터 그 자체와 매핑을 하기 때문에 SQL을 직접 작성하지 않는다. 따라서, 데이터 정보가 수정되면 객체만 바꿔주면 된다는 장점이 있다.
Java에서 사용하는 대표적인 ORM으로는 JPA와 Hibernate가 있다. JPA가 등장하기 전에는 Mybatis라는 Object Mapping 기술을 이용했는데 Mybatis는 직접 개발자가 SQL 쿼리를 작성해서 Java 객체와 매핑해야했다. Mybatis는 데이터값을 변경하면 사용되고 있던 DTO와 함께 수정해주어야 하기때문에 번거롭지만 ORM보다는 복잡한 쿼리를 처리하기에 좋다.
MyBatis보다 JPA를 사용하기를 권하는 이유
JPA가 아래와 같은 강점이 있기 때문이다.
1. 엔티티에 맞는 테이블 생성 + DB 생성 편리 (자동으로 만들어줌)
2. 객체 지향 중심의 개발 가능 (객체지향언어인 자바와 잘맞음)
3. 테스트 작성 용이
설명
Repository 계층은 데이터베이스와 데이터를 주고 받는 계층이므로 단위 테스트로 작성하기 보다 DB와 연결하여 실제 쿼리를 날리는 통합 테스트로 진행하는 것이 좋다. 위에서 살펴보았듯 JPA는 테이블을 자동으로 만들어주므로 테스트를 작성하기에 매우 좋다.
Spring은 Repository 테스트를 위한 @DataJpaTest를 제공하고 있는데, @DataJpaTest를 이용하면 기본적으로 인메모리 데이터베이스(h2)로 연결이 된다. 그리고 테이블 생성 옵션을 주면 우리는 순쉽게 Repository 계층을 테스트할 수 있다.
4. 기본적인 CRUD 자동화
5. 복잡한 쿼리는 QueryDSL을 사용해 처리
설명
MyBatis의 장점 중 하나는 직접 쿼리를 작성하므로 복잡한 쿼리를 다루기 유용하다는 것입니다. 실제로 JPA를 이용하다보면 동적 쿼리를 처리하기가 매우 어렵다.
하지만 이러한 경우에는 MyBatis를 이용하기보다 QueryDSL 이라는 오픈소스를 사용한다면 문제를 해결할 수 있다. 아래의 코드는 QueryDSL을 이용한 예시이며 자바 언어로 매우 직관적인 쿼리를 작성할 수 있다는 장점이 있다.
++추가 정리
Connection pool
커넥션 풀은 데이터베이스 연결을 효율적으로 관리하고 재사용하는데 사용되는 기술이다.
Connection pooling은 각 데이터베이스 작업에 대해 데이터베이스 연결을 열고닫는 오버헤드를 최소화하는데 도움이 되기 때문에 성능이 향상된다.
Connection Pooling에 사용되는 일반적인 Java 라이브러리는 다음과 같다.
- Apache DBCP
- HikariCP
- C3P0
이러한 Connection Pool 라이브러리는 일반적으로 보다 효율적인 방식으로 데이터베이스 연결을 관리하기 위해 JPA 또는 MyBatis와 같은 지속성 프레임워크 또는 직접 JDBC와 함께 사용된다.
자세한 정리 ⇒ JDBC와 Connection Pool
참고
- https://velog.io/@rladuswl/ORM%EC%9D%98-%EA%B0%9C%EB%85%90-JPA%EC%99%80-MyBatis-%EC%B0%A8%EC%9D%B4
- https://mangkyu.tistory.com/20