JPA를 사용하면서 객체 그래프 탐색할 때 실행되는 쿼리가 궁금해졌다. JPA는 연관관계만 설정해 주면 해당 연관관계에 접근했을 때, 자동으로 쿼리를 실행해 준다. 이 자동으로 실행되는 쿼리는 우리가 예상하지 못하는 무수히 많은 수의 쿼리가 실행될 수도 있고, 성능상 좋지 못한 쿼리가 실행될 수도 있다. 그래서 예상되는 쿼리를 데이터베이스 조인을 통해 우리가 SQL로 직접 작성하여 실행함으로써 연관관계에 대한 객체 그래프 탐색을 SQL을 통해 구현하기로 하였다.
혹시나 다음에 다른 ORM으로 변경되더라도, 우리가 작성한 코드의 큰 변경없이 마이그레이션하기 좋고, 유지보수가 용이한 코드를 구성하고 싶었다.
지금까지 JPA의 연관관계를 적극 활용해 오다 보니, 데이터베이스 테이블 자체에 대한 이해도가 부족한 것을 느꼈다. 부족한 이해도를 높이기 위해 엔티티 클래스를 RDB 테이블과 유사한 형태를 가지게끔 했다.
어떤 기능이 필요하면 외부 라이브러리를 그냥 무작정 사용을 하는데 이렇게 되면 문제점이 일단 첫 번째 문제 이런 라이브러리에 너무 의존을 하게 되는 것이고, 두 번째는 만약에 스프링 버전을 업그레이드해야 한다면 어떤 라이브러리는 스프링 버전 업그레이드에 대해 호환되는 것도 있지만 그렇지 않은 라이브러리도 있을 수 있어서 이것이 개발을 진행하는데 발목을 잡을 수 있다.
연관관계를 형성하지 않으면서 어떤 상황에서 연관관계를 형성해야 하는지, 정확한 연관관계 형성 시점에 대해서 알았다.
객체 그래프 탐색에 필요한 SQL을 일일이 작성하면서 SQL의 대한 숙련도가 높아졌다.
우리가 일하게 될 모든 회사가 JPA를 사용하지 않는다. mybatis를 사용할 수 도 있고, JPA와는 다른 ORM을 사용할 수도 있기 때문에 좀 더 근본적인 학습을 통해서 다른 라이브러리를 수월하게 사용할 수 있게 되었다.
JPA
JPA ( Java Persistence API )
자바에서 데이터베이스를 사용하는 데 도움을 주는 API입니다. JPA는 객체 관계 매핑(ORM)을 지원하며, 개발자가 자바 객체와 데이터베이스 테이블 간의 매핑을 간편하게 수행할 수 있도록 도와줍니다.
JPA는 데이터베이스와 자바 어플리케이션 간의 상호작용을 추상화하고, 객체 지향 프로그래밍(OOP) 원칙에 따라 개발자가 코드를 작성할 수 있게 해줍니다. 이를 통해 개발자는 SQL 쿼리를 직접 작성하지 않고도 데이터베이스에 접근하고 조작할 수 있습니다.
JPA는 ORM 프레임워크의 표준 스펙이며, 여러 구현체가 존재합니다. 가장 널리 사용되는 JPA 구현체 중 하나는 Hibernate입니다. Hibernate는 JPA 스펙을 구현한 오픈 소스 ORM 프레임워크로, 객체와 데이터베이스 간의 매핑 및 상호작용을 담당합니다.
JPA 미사용 장점
JPA를 사용하지 않는 경우에도 몇 가지 장점이 있을 수 있습니다. 그러나 이는 상황에 따라 다르며, 일반적으로 JPA를 사용하는 것이 객체 지향적인 개발과 데이터베이스 상호작용을 더 간소화하고 추상화하는 데 도움이 되기 때문에 대부분의 경우에는 JPA를 선호합니다. 그럼에도 불구하고, JPA를 사용하지 않을 때의 일부 장점은 다음과 같을 수 있습니다:
직접적인 제어
JPA를 사용하지 않으면 SQL 쿼리를 직접 작성하므로 데이터베이스에 대한 더 직접적인 제어가 가능합니다. 일부 개발자들은 이러한 직접적인 접근이 특정 성능 최적화나 특수한 데이터베이스 동작을 위해 필요하다고 여길 수 있습니다.
더 많은 유연성
특정 데이터베이스에 종속되지 않고, SQL 쿼리를 직접 작성함으로써 더 많은 유연성을 얻을 수 있습니다. 특정 데이터베이스의 특성을 더 직접적으로 활용할 수 있습니다.
간단한 프로젝트
작은 규모의 프로젝트나 간단한 애플리케이션에서는 JPA를 사용하지 않는 것이 더 간단할 수 있습니다. ORM의 복잡성과 학습 곡선을 피하고자 하는 경우가 있습니다.
성능 최적화
특정 케이스에서는 JPA의 추상화 계층이 성능에 영향을 미칠 수 있습니다. 일부 개발자는 직접 SQL을 작성함으로써 성능을 최적화하려고 할 수 있습니다.
JPA를 사용할지 여부는 프로젝트의 규모, 복잡성, 유지보수 가능성, 팀의 스킬셋 등을 고려하여 결정해야 합니다. 큰 프로젝트에서는 일반적으로 JPA나 다른 ORM 도구를 사용하는 것이 개발 생산성을 높이고 유지보수를 쉽게 만들 수 있습니다.
JPA 미사용 단점
JPA를 사용하지 않는다면, 개발자는 데이터베이스와의 상호작용을 직접 처리해야 합니다. 전통적인 JDBC(Java Database Connectivity)를 사용하거나 다른 데이터베이스 연동 기술을 활용하여 SQL 쿼리를 작성하고, 데이터베이스와의 연결, 트랜잭션 관리, 결과셋 처리 등을 직접 다루어야 합니다.
JPA를 사용하지 않을 때의 몇 가지 특징은 다음과 같습니다:
직접 SQL 작성
JPA를 사용하지 않으면 SQL 쿼리를 직접 작성해야 합니다. 이는 데이터베이스 특정한 쿼리 및 스키마 변경 시에 애플리케이션 코드를 수정해야 할 수도 있음을 의미합니다.
ORM을 사용하지 않음
JPA는 객체와 데이터베이스 간의 매핑을 지원하는 ORM 기술을 제공하는데, 이를 사용하지 않을 경우 개발자가 직접 객체와 테이블 간의 매핑을 처리해야 합니다.
데이터베이스 연결 및 트랜잭션 관리
JPA는 이러한 부분을 추상화하고 단순화합니다. 그러나 JPA를 사용하지 않으면 데이터베이스와의 연결, 트랜잭션 관리 등을 직접 처리해야 합니다.
반복적인 코드 작성
JPA를 사용하지 않으면 데이터베이스와의 상호작용을 위한 반복적이고 일상적인 코드를 직접 작성해야 합니다.
JPA를 사용하지 않는 경우, 특히 대규모 애플리케이션에서는 유지보수와 생산성이 떨어질 수 있습니다. 반면에 JPA를 사용하면 개발자는 더 객체 지향적이고 추상화된 레벨에서 데이터베이스와 상호작용할 수 있으며, 코드의 가독성과 유지보수성이 향상될 수 있습니다.
JPA 사용하는 방법
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
@ID으로 해당 변수가 PK(Primary key)라는것을 지정하고
@GeneratedValue를 통해 자동생성, 생성전략은 IDENTITY, 고유키 생성전략을 사용한다. 이는 MySQL의 AUTO_INCRESEMENT와 같은 역할을 한다.
그다음 Table의 Column과 연결할 변수들을 @Column을 사용하여 선언을 해주면 된다.
@Entity
@Getter // Getter, Setter은 Lombok 라이브러리이다. 각 변수의 Getter, Setter Method를 만들어준다.
@Setter
public class Person{
@ID
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column
private String name;
}
@Repository
public interface PersonRepo extends JpaRepository<Person,Long>{
@Query("Select this from Person this where this.isMale=:isMale") // 쿼리문을 정의해서 쓸수도 있다.
public List<Person> getPersons(@Param("isMale")boolean isMale);
//규칙에 맞게 Method이름을 만들면 자동으로 Query문을 정의하지 않아도 된다.
public List<Person> findAllByIsMale(boolean isMale);
}
ORM
ORM ( Object-Relational Mapping )
객체와 관계형 데이터베이스를 매핑한다는 뜻
ORM 프레임워크는 객체와 테이블을 매핑해 패러다임의 불일치를 개발자 대신 해결해준다. 객체는 객체대로 생성하고, 데이터베이스는 데이터베이스에 맞도록 설계를 가능하게 해준다. 개발자는 이를 매핑하는 방법만 전달해주면 된다.
단점