반응형
ORM(Object-Relational Mapping)
- 객체-관계 매핑
- 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해 주는 것
- 객체 지향 프로그래밍 : 클래스, 관계형 데이터베이스 : 테이블
- 객체 지향 프로그래밍 언어를 사용하여 호환되지 않는 유형의 시스템 간에 데이터를 변환하는 프로그래밍 기술
종류
- Flask : SQLAlchemy
- Django : 내장 ORM
- Node.js : Sequalize
- Java : Hybernate, JPA
- GraphQL : Prisma
동작 원리
- ORM Framework 메소드와 백엔드 개발언어를 이용해 SQL 구문을 자동으로 생성하고 DB 서버에 전달하는 것
장점
- 개발자가 복잡한 SQL 쿼리를 작성할 필요가 없음
- 객체 지향 프로그래밍의 장점을 활용하여 코드 재사용성과 유지보수성을 높일 수 있음
- 특정 데이터베이스에 의존하지 않고 코드가 작동함
- 메소드 단위로 트랜잭션을 관리해 데이터의 일관성을 쉽게 유지할 수 있음(@Transactional)
단점
- 특정 데이터베이스에서만 지원하는 기능을 사용하려면 직접 SQL 쿼리를 작성해야 함(윈도우 함수, 서브쿼리)
- ORM이 생성한 SQL 쿼리는 코드에서 직접 확인하기 어려워 문제가 발생했을 때 원인을 찾기 힘들 수 있음
- 복잡한 쿼리를 작성해야 하는 경우 ORM이 저동으로 생성하는 SQL이 비효율적일 수 있음(다중 조인 쿼리를 사용할 때 ORM이 생성한 쿼리가 성능을 저하시킬 수 있음)
ORM의 단점을 극복하기 위해 사용하는 방법
- Native Query 사용 : JPA에서 SQL을 직접 작성하여 DB와 상호작용하는 방법. SQL문법을 그대로 사용
@PersistenceContext
private EntityManager entityManager;
public List<User> findUsersByCustomQuery(String email) {
String sql = "SELECT * FROM users WHERE email = :email";
return entityManager.createNativeQuery(sql, User.class)
.setParameter("email", email)
.getResultList();
}
- JPQL(Java Persistence Query Language) 사용
@Query("SELECT u FROM User u WHERE u.email = :email")
List<User> findByEmail(@Param("email") String email);
- Hibernate Criteria API 사용
public List<User> findUsersByCriteria(String email) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> userRoot = criteriaQuery.from(User.class);
criteriaQuery.select(userRoot).where(criteriaBuilder.equal(userRoot.get("email"), email));
return entityManager.createQuery(criteriaQuery).getResultList();
}
- Spring Data JPA의 @Query 어노테이션 사용
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
User findByEmail(String email);
}
- Mybatis 사용
<select id="selectUserByEmail" parameterType="String" resultType="User">
SELECT id, name, email FROM users WHERE email = #{email}
</select>
Mybatis
- SQL Mapper
- DB를 쉽게 다룰 수 있도록 도와주는 오픈 소스 ORM(Object-Relational Mapping) 프레임워크
- JAVA의 관계형 DB 프로그래밍을 좀 더 쉽게 도와주는 Persistence Framework(데이터를 다루는 클래스 및 설정파일 집합)
- XML 파일 형태인 mapper를 통해 프로그램 코드로부터 SQL 쿼리가 분리되는 환경을 제공하고 JAVA와 매핑하는 작업을 도와줌
- 주로 SQL 쿼리를 XML 파일이나 어노테이션을 통해 정의하고, 이를 JAVA 객체에 매핑하여 DB와의 CRUD 작업을 수행할 수 있도록 도움
사용 목적
- DB 쿼리와 프로그래밍 언어 코드를 분리하여 유지보수성과 생산성을 높이는 것
장점
- 쿼리를 분리하기 때문에 쿼리 수정 후 JAVA 파일을 재빌드 할 필요가 없음
- 동적 쿼리를 작성할 수 있음
사용 방법
- XML만을 이용한 SQL문 설정
- Annotation과 인터페이스만을 이용하여 SQL문 설정
- 인터페이스와 XML로 작성된 SQL문 활용
동적 쿼리
- 실행 시점에 조건에 따라 SQL 쿼리를 동적으로 생성하는 것 -> DB의 검색 조건이나 결괏값 등이 동적으로 변할 때 유용하게 사용됨
- 태그를 사용하여 동적 쿼리 작성
- 조건문
<if>
: 단일 조건<choose>, <when>, <otherwise>
: 다중 조건
<choose> <when test="조건1"> 조건1이 참일 때 추가될 문장 </when> <when test="조건2"> 조건1이 거짓이고, 조건2가 참일 때 추가될 문장 </when> <otherwise> 조건1, 조건2 모두 거짓일 때 실행할 문장 </otherwise> </choose>
<where>
: 조건 특화 엘리먼트. where 내부에는 조건을 표현할 수 있는 if나 choose가 사용될 수 있음
SELECT * <WHERE> <if test="조건"> AND 칼럼명 = #{변수} </if> <if test="조건"> AND 칼럼명 = #{변수} </if> </WHERE>
<set>
UPDATE 테이블명 <set> <if test="조건"> 컬럼명 = #{변수}, </if> <if test="조건"> 컬럼명 = #{변수}, </if> </set>
<trim>
- prefix : 실행될 쿼리의 가장 앞에 문자 추가
- prefixOverrides : 실행될 쿼리의 가장 앞에 해당하는 문자가 있는 경우 지움
- suffix : 실행될 쿼리의 가장 뒤에 문자 추가
- suffixOverrides : 실행될 쿼리의 가장 뒤에 문자가 있는 경우 지움
<update id="updateStudentInfo"> <!-- 매퍼에서 업데이트 쿼리 호출 시 사용 -->
UPDATE
STUDENT
<trim prefix="SET" prefixOverrides="," suffixOverrides=","> <!-- SQL 쿼리의 시작 부분에 SET 키워드를 추가하고 시작과 끝에 콤마를 제거 -->
<if test='age != null age != ""'>
AGE = #{age},
</if>
<if test='name != null name != ""'>
NAME = #{name},
</if>
<if test='phoneNumber != null phoneNumber != ""'>
PHONE_NUMBER = #{phoneNumber},
</if>
</trim>
</update>`
Mybatis vs ORM
- SQL 작성 방식
- Mybatis : 쿼리를 명시적으로 작성. 복잡한 쿼리나 최적화가 필요한 쿼리를 직접 작성할 수 있음
- ORM : 쿼리를 자동으로 생성. CRUD 작업을 메소드 호출로 수행할 수 있음
- 제어 수준
- Mybatis : 개발자가 필요한 SQL을 직접 작성하므로 복잡한 쿼리에 대한 최적화가 용이
- ORM : 객체 지향적 접근을 제공하지만 SQL 쿼리에 대한 제어가 제한적
- 매핑 방식
- Mybatis : 개발자가 XML 파일에서 각 SQL 쿼리와 결과 객체 간의 매핑을 정의
- ORM : @Entity를 사용하여 클래스와 테이블 간의 매핑을 자동으로 처리
XML
- SQL 매퍼를 정의하는 데 사용됨
- SQL 쿼리와 DB와의 매핑을 명시적으로 설정하는 역할을 함
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUser" parameterType="int" resultType="User">
SELECT id, name, email
FROM users
WHERE id = #{id}
</select>
<insert id="insertUser" parameterType="User">
INSERT INTO users (name, email) VALUES (#{name}, #{email})
</insert>
</mapper>
- namespace : 매퍼의 고유 이름 공간을 정의(다른 이름을 가진 매퍼와 구분. Mapper 인터페이스에서 메소드를 호출할 때 사용됨)
- id : 쿼리의 고유 식별자
- parameterType : 쿼리의 입력 매개변수 타입 지정
- resultType : 쿼리 결과를 매핑할 JAVA 클래스의 타입 설정
Mapper
- SQL 쿼리와 JAVA 객체 간의 매핑을 정의하는 인터페이스
- XML 파일이나 어노테이션을 통해 정의할 수 있음
- Mapping 파일에 기재된 SQL을 호출하기 위한 인터페이스
- Mapper 인터페이스의 메소드를 호출하여 SQL 쿼리를 실행함
public interface UserMapper {
User selectUser(int id);
void insertUser(User user);
}
반응형
'DB > Mybatis' 카테고리의 다른 글
Dynamic SQL(동적 SQL) (1) | 2025.01.31 |
---|---|
Mapper XML (0) | 2025.01.31 |
저장 프로시저, Mybatis에서의 사용(CALLABLE) (3) | 2025.01.31 |