Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
Tags
- spring aop
- PreparedStatement
- 스프링
- 프론트엔드
- 백엔드
- redmine
- 인덱스
- Si
- AOP
- It
- 엘라스틱서치
- 웹프론트
- kibana
- java
- 프로젝트관리
- spring
- 비전공개발자
- 검색
- 오라클
- db
- frontend
- PM
- 데이터베이스
- 개발자
- Database
- 이슈관리
- 일감관리
- elasticsearch
- 레드마인
- 자바
Archives
- Today
- Total
리타의 저장소
JAVA | JPA와 Mybatis에서의 PreparedStatement 동작방식 본문

같이 스터디를 하는 스터디원들과 PreparedStatement에 대해서 이야기를 하다가, 실제 담당하고 있는 서비스에서 PreparedStatement를 사용하냐고 물었을 때 다들 사용하지 않는다고 했다.
대체로 JPA 혹은 Mybatis를 사용중이라 업무를 하면서 마주할일이 거의 없다는 것이었다. 근데, 또 여기서 궁금한게 생겼다. 과연 진짜 그들은 PreparedStatement를 사용하지 않는 것일까?
핵심부터 말하자면
JPA, MyBatis 모두 실제 SQL 실행할 때 JDBC API를 쓰고, 그 안에서 PreparedStatement를 사용한다.
즉, 직접 pstmt.setInt(1, xxx) 라고 쓰지 않아도 프레임워크가 내부에서 알아서 PreparedStatement를 만들고 파라미터를 바인딩해서 실행한다는 것이다.
* JDBC API란 ? Java에서 데이터베이스와 연결하고 SQL을 실행할 수 있게 해주는 표준 인터페이스.
JPA에서의 PreparedStatement 동작 방식
- JPA (Hibernate 기준):
- EntityManager.find() 같은 메서드를 호출하거나,
- JPQL, CriteriaQuery, @Query 같은 걸 쓰면,
- Hibernate가 SQL을 생성하고,
- JDBC Connection을 열고,
- 그 위에 PreparedStatement를 생성해서,
- 바인딩 (setInt(), setString() 등)하고,
- executeQuery() 로 실행.
실제 내부 예시
Hibernate 내부 예시 :
PreparedStatement pstmt = connection.prepareStatement("SELECT * FROM users WHERE id = ?");
pstmt.setInt(1, 10);
ResultSet rs = pstmt.executeQuery();
➡️ 실제 코드의 경우 find(User.class, id) 한 줄 썼지만,
➡️ Hibernate는 내부에서 PreparedStatement를 만들어서 처리.
JPA에서의 코드 예시:
User user = entityManager.find(User.class, 10);
- "find" 메서드 하나로 SQL 준비 + 파라미터 바인딩 + 실행 다 해줌
- PreparedStatement로 처리되기 때문에, Injection 걱정 없음
MyBatis에서는 어떻게 할까?
MyBatis는 SQL Mapper. 직접 SQL을 XML이나 어노테이션으로 적게 됨.
MyBatis Mapper 예시:
<select id="findUserById" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
여기서 #{id} 를 보면,
- #{} 표기는 "PreparedStatement의 ? "처럼 작동.
- MyBatis는 이걸 자동으로 바인딩해줌.
내부 처리 흐름
MyBatis 내부 코드 예시:
PreparedStatement pstmt = connection.prepareStatement("SELECT * FROM users WHERE id = ?");
pstmt.setInt(1, id);
ResultSet rs = pstmt.executeQuery();
➡️ 즉, MyBatis도 무조건 PreparedStatement로 변환해서 실행.
* 참고 *
- #{id} : 바인딩 (PreparedStatement, 안전함)
- ${id} : 그냥 문자열 치환 (PreparedStatement 안씀, Injection 위험)
MyBatis 쓸 때 #{id} 방식을 쓰는게 더 좋은 이유

'Dev > Backend' 카테고리의 다른 글
| Spring AOP | 서비스 호출 전에 로깅, 꼭 AOP에서 해야만 하나? (0) | 2025.10.11 |
|---|---|
| JAVA | JVM이란 무엇인가? (0) | 2025.10.11 |
| JAVA | DB Call 최소화 (Feat. PreparedStatement) (0) | 2025.10.11 |
| JAVA | Spring에서의 PreparedStatement (0) | 2025.10.11 |
| JAVA | Java에서 DB 커넥션을 얻는 방법 #2 (feat. PreparedStatement) (0) | 2025.10.11 |