-
[Spring] Mybatis, JPA, ORM에 대해서 간단하게 알아보자백엔드/Spring 2022. 5. 21. 00:07
[Spring] Mybatis, JPA, ORM에 대해서 간단하게 알아보자
API 개발을 하기 위해서는, 데이터베이스를 기동하여 질의문을 동작시켜야 합니다.
이를 위해서는 반드시 질의문을 돌릴 수 있는 “Mybatis”와 “JPA”를 학습해야 합니다.
Mybatis와 JPA, ORM을 모르는 분들을 위해서 정리하였습니다.1. Mybatis
- Mybatis 템플릿 - https://github.com/rojae/mybatis-demo
- Mybatis JSP 게시판 예제 : https://github.com/rojae/SpringBoot-BBS-demo
XML 파일에서 Query를 직접 작성하여, 추출되는 결과를 XML 문법을 통해서
자바 Class 파일로 변환합니다.마이바티스는 아래와 같은 모습을 가집니다.
<?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="kr.imcf.mybatis.mapper.TblAccountMapper"> <!-- 1. "BaseResultMap"이라는 ID를 가지고, 이 부분으로 kr.imcf.mybatis.domain.TblAccount 클래스로 변환이 가능해요 --> <resultMap id="BaseResultMap" type="kr.imcf.mybatis.domain.TblAccount"> <result column="id" jdbcType="VARCHAR" property="id" /> <result column="password" jdbcType="VARCHAR" property="password" /> </resultMap> <insert id="insert" parameterType="kr.imcf.mybatis.domain.TblAccount"> insert into tbl_account (id, password) values (#{id,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}) </insert> <!-- 2. 쿼리 결과가 "BaseResultMap"를 따라가서, TblAccount에 담깁니다 --> <select id="select" resultMap="BaseResultMap"> select * from tbl_account </select> </mapper>
여기 사실 엄청난 문제가 있습니다. 😢
XML은 텍스트라서 컴파일 시점에 오류를 잡을 수가 없어요.
이 말은, XML에서 오류가 있으면 RUNTIME 시점에서 감지가 된다는 이야기예요.
한 글자만 틀려도, 이클립스가 알려주지 않아요.. 💢
2. ORM이란?
- 데이터베이스에 종속적이다.
ORM을 설명하기 앞서, 우리는 지금까지 어떻게 프로그래밍 언어를 사용했는지 알아야해요.
어플리케이션에서 데이터베이스를 연결하여, DB의 데이터를 조작하는 방식으로 개발을 해왔어요. 그리고 이런 방식은 “데이터베이스에 종속적이다” 라고 표현합니다.
예를 들면, 우리가 DB에서 데이터를 꺼내와서, JAVA에서 값을 바꿉니다.
그렇다고 DB 테이블에 있는 값이 바뀌지 않습니다.
우리는 이것을 “어플리케이션이 DB에 종속된다”라고 말합니다.- ORM은 어플리케이션에서 UPDATE가 된다고요? 🤔
- 설마가 그 진짜이긴 합니다.
자바에서 “PERSIST” 영속화 처리를 통해서, 변경 감지가 가능합니다.
이러한 배경으로, 천재 개발자들이 고민 끝에 ORM을 최적으로 사용하기 위해서 Querydsl이라는 놈을 만들었습니다.
- 아래는 그 예제예요.
QueryResults<Member> results = query.selectFrom(member) .where(member.age.gt(30)) .orderBy(member.username.desc()) .limit(2) .fetchResults();
이 소스는 아래 질의문이랑 동일합니다.
SELECT * FROM member m WHERE m.age > 30 ORDER BY m.username DESC LIMIT 2;
JAVA에서 SQL 처리를 위한 멀고 먼 역사
왜 Mybatis와 Querydsl이 나왔는지 이해하면, 기억하기도 쉬울 것 같아요.
1. 문자열 SQL 처리
초창기에 자바는 아래와 같은 형태로 질의를 처리했어요.
Connection conn = null; Statement stmt = null; String sql = "INSERT tbl_account (id, password) VALUES('" + id +"'," + password + ")"; conn = DriverManager.getConnection("jdbc:oracle:thin:@" + ip + ":" + port + ":" + sid, id, password); stmt = conn.createStatement(); stmt.executeQuery(sql); stmt.close(); conn.close();
문제는 이게 문자열이라는거예요. SQL 오류를 탐지하기 위해서는…
“컴파일 시점”이 아니라, 쿼리를 돌리는 “런타임” 시점에 알게되요.
따옴표 하나만 틀려도, API 하나가 먹통이 되는거죠.많은 개발자들이 고민을 많이했어요.
결국 XML 파일과 CLASS를 상호간에 변환 가능하도록 처리하고
쿼리를 담기로 했어요. (이래도 컴파일 시점에 오류 탐지는 불가능했습니다)
이때 XML을 Mybatis XML Mapper라고 합니다.2. Mybatis 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="kr.imcf.mybatis.mapper.TblAccountMapper"> <!-- 1. "BaseResultMap"이라는 ID를 가지고, 이 부분으로 kr.imcf.mybatis.domain.TblAccount 클래스로 변환이 가능해요 --> <resultMap id="BaseResultMap" type="kr.imcf.mybatis.domain.TblAccount"> <result column="id" jdbcType="VARCHAR" property="id" /> <result column="password" jdbcType="VARCHAR" property="password" /> </resultMap> <insert id="insert" parameterType="kr.imcf.mybatis.domain.TblAccount"> insert into tbl_account (id, password) values (#{id,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}) </insert> <!-- 2. 쿼리 결과가 "BaseResultMap"를 따라가서, TblAccount에 담깁니다 --> <select id="select" resultMap="BaseResultMap"> select * from tbl_account </select> </mapper>
위처럼 XML로 해도 문자열인건 변함이 없었어요.
“컴파일 시점”에 오류를 잡기 위해서, ORM이라는 놈을 적절히 사용하면서
Querydsl이라는 친구가 나타납니다.아래에서 쿼리문법이 틀리면, 컴파일 시점에서 알려줍니다.
(이클립스 빨간줄)3. Querydsl (With JPA)
QueryResults<Member> results = query.selectFrom(member) .where(member.age.gt(30)) .orderBy(member.username.desc()) .limit(2) .fetchResults();
이 과정으로 개발자들이 생산성이 증대했고, 많은 자바 개발자들의 사랑을 받고 있어요.
부록
ORM과 JPA에 대해서, 살짝 공부하고 싶다면
아래 글이 될 수 있을 것 같아요.Spring JPA 객체의 상태에 대해서 알아보자 (Transient, Persistent, Detached)
반응형'백엔드 > Spring' 카테고리의 다른 글
[Spring] RestTemplate을 편리하게 사용하자 (샘플 포함) (2) 2022.06.12 [Spring] 인텔리제이에서 Mybatis Generator 사용하는 법 (0) 2022.06.12 [Spring] AOP 기능을 사용해서, 어노테이션으로 로그를 남기자 (annotation logging) (2) 2022.04.30 [Spring] Servlet 응답, 요청 객체를 얻는 방법 (HttpServletRequest, HttpServletResponse) (0) 2021.11.04