서론
Java로 된 서버와 데이터베이스를 연동할 때 흔히들 MyBatis 를 사용한다.
Java 변수를 넘겨서 SQL 문에 채워 DB에 명령을 보내는데,
Java에서 String 을 완성시키는 원초적인 방법은
유지보수도 망치고, 디버깅도 어렵기 때문에,
XML형태를 통해 SQL문을 관리하는 MyBatis도 꽤나 큰 장점을 갖고 있었다.
스프링에서는 JPA + 쿼리 조합을 많이 사용하는데,
JPA는 SQL의 모든 요소를 @어노테이션을 통해 객체화 시킨다.
JPA에서 DB 로 쿼리를 날리있는 방법은 3가지이다:
1. 리포지터리 메서드(스프링 데이터 JPA, 후술)
2. @NamedQuery ( 변수 하나에 SQL문 하나를 미리 할당해놓는 정적 쿼리, 아래 예제)
@NamedQuery(
name="MemberJPQL.findByName",
query="select m from MemberJPQL m where m.username = :username"
)
3. @Query ( "select * from someTable" )
여기서 말하는 Query는 JPQL 을 말한다.
MySQL 과 같은 일반적인 쿼리를 쓰려면 NativeQuery 를 써야한다.
밑에서 JPQL에 대한 것도 다뤄보자.
QueryDSL 의 등장
하지만 이것도 저것도 마음에 안드는 개발자들이 수많은 시도 끝에,
누군가가 만들어낸 QueryDSL 하나로 인해
쿼리는 디게 쉬워졌다.
바로 코드를 보자.
public List<Contents> findAll(contentsSearch contentsSearch) {
MyContents content = MyContents.content;
MyAuther author = MyAuhor.author;
return query
.select(content)
.from(content)
.join(content.author, author)
.where(statusEq(contentsSearch.getContentStatus()),
nameLike(contentsSearch.getAutherName()))
.limit(1000)
.fetch();
}
private BooleanExpression statusEq(ContentStatus statusCond) {
if (statusCond == null) {
return null;
}
return content.status.eq(statusCond);
}
private BooleanExpression nameLike(String nameCond) {
if (!StringUtils.hasText(nameCond)) {
return null;
}
return author.name.like(nameCond);
}
return query .select .from .join 이 보이는가?
혁신적이지 아니할 수 없다는 것은 반박할 수 없지 않지 않다.
이렇게 JAVA 코드이며 직관적인 방식으로
동적쿼리를 생성하면 생기는 이점은 생각보다 엄청나다
- 이클립스 / 인텔리제이 와 같은 컴파일러 문법 자동교정의 혜택을 받는다.
스펠링 에러가 잡히니 컴파일하기 전에 오류를 발견할 수 있고,
자동완성이 된다. - 코드를 재사용하기 쉽다. 자바코드니까!
- JPQL 을 기반으로 하지만 JPQL보다 훨씬 가독성이 높다.
그렇다면 여기서 잠시 JPQL이 뭔지 알아보도록 하자.
JPQL 에 대한 간단한 고찰
JPQL은 JPA + SQL 의 조합이 어원... 인줄 알았으나,
JPQL(Java Persistence Query Language)의 줄인말이며, 객체지향형 쿼리이다.
SQL문인데 이제 JPA 전용 SQL문으로 다시 탄생한 문법이다.
Result객체 = 엔티티객체 . JPA함수( " JPQL 문자열 " )
의 형태로 나타난다.
장점은 오라클이건 MySQL이건 설정 변경만 해주면 코드수정없이 DB이전이 된다.
특징은 복잡한 SQL작업을 위해 탄생한 놈이라, 각종 조인, 프로젝션, 페이징 등 거의 모든 기능이 존재한다.
간단한 Select Delete 같은 문법은 스프링 데이터 JPA* 사용을 추천한다.
(스프링 데이터 JPA의 관한 설명을 원한다면 아래 더보기 클릭)
스프링 데이터JPA에 대한 간단한 설명:
스프링 데이터 JPA는 간단한 select, delete 등 기능들을 전부 구현해놓은 라이브러리이다.
JPA를 활용하기 때문에 JPA에 대한 이해도가 필요하다.
물론 JPA에도 간단한 SQL 문 외에 수많은 기능들이 있지만,
한계점이 명확하기 때문에 잘 모르고 썼다가 추후에 코드를 갈아 엎는 경우도 많다고 하니,
잘 알아보고 쓰도록 하자.
간단하게 스프링 데이터 JPA 유무를 비교해보자면,
@Repository
@RequireArgsConstructor
public class MemberRepository {
private final EntityManager;
public List<Member> findByName(String name) {
return em.createQuery("select m from Member m", Member.class)
.setParameter("name", name)
.getResultList();
}
}
이 10줄의 코드를
public interface MemberRepository extends JpaRepository<Member, Long> {
List<Member> findByName(String name);
}
이렇게 3줄로 끝낸다. 이미 JpaRepository 안에 findByName() 이 구현되어있기 때문.
아무튼 다시 JPQL로 돌아와서,
String jpql = "select m from Member as m where m.username = 'kim'";
List<Member> resultList = em.createQuery(jpql, Member.class).getResultList();
이게 JPQL 쿼리문으로 JPA를 사용한 간단한 예제이다.
언뜻보면 SQL과 별 차이 없어보이지만, 결정적인 차이점은
JPQL에 들어가는 모든 변수는 데이터베이스나 테이블이 아닌 객체이다.
jpql = "select m from Member as m where m.username = 'kim'"
m도 객체, from 절의 Member 도 객체 ! from 테이블 아니고 from 객체란 말임!
따라서 애석하게도 DB를 몰라야 더 배우기 쉽다고 유우-머를 칠 정도의 차이점을 가진다.
검색 자체를 엔티티 객체에서 하니까.
아무튼...
JPA, JPQL, QueryDSL 에 대해서 빠르게 알아봤다.
(다듬는중인 글입니다.)
참고 :
https://data-make.tistory.com/614
https://ict-nroo.tistory.com/116
도움이 되셨다면 ♡공감 및 ↓광고클릭으로 응원해주세욥 :D