@Mapper

코딩냥이·2024년 9월 10일

Annotation

목록 보기
8/34

@Mapper

@Mapper 어노테이션은 MyBatis-Spring-Boot 통합에서 중요한 역할을 하는 어노테이션입니다. 이 어노테이션은 인터페이스를 MyBatis mapper로 지정하는 데 사용됩니다.

기능

  • 인터페이스를 MyBatis mapper로 표시합니다.
  • 스프링의 컴포넌트 스캔 대상이 되어 자동으로 빈으로 등록됩니다.
  • MyBatis가 해당 인터페이스의 구현체를 자동으로 생성하도록 합니다.

사용 방법

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM users WHERE id = #{id}")
    User getUserById(Long id);

    @Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")
    int insertUser(User user);

    @Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")
    int updateUser(User user);

    @Delete("DELETE FROM users WHERE id = #{id}")
    int deleteUser(Long id);
}

주요 특징

  1. 인터페이스 기반: 구현 클래스를 직접 작성할 필요 없이 인터페이스만 정의하면 됩니다.
  2. SQL 매핑: 어노테이션 또는 XML을 통해 SQL을 매핑할 수 있습니다.
  3. 자동 빈 등록: @Mapper가 붙은 인터페이스는 스프링 컨테이너에 자동으로 빈으로 등록됩니다.
  4. 타입 안전성: 컴파일 시점에 타입 체크가 가능합니다.

MyBatis-Spring-Boot-Starter 설정

@Mapper를 사용하기 위해서는 MyBatis-Spring-Boot-Starter를 프로젝트에 추가해야 합니다:

Maven

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

Gradle

Gradle을 사용하는 경우, build.gradle 파일에 다음 의존성을 추가합니다:

dependencies {
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
}

만약 Gradle Kotlin DSL을 사용한다면, build.gradle.kts 파일에 다음과 같이 추가합니다:

dependencies {
    implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0")
}

@Mapper vs @Repository

@Mapper는 MyBatis에 특화된 어노테이션인 반면, @Repository는 스프링의 일반적인 데이터 접근 계층 컴포넌트를 나타냅니다:

  • @Mapper: MyBatis가 구현체를 자동으로 생성합니다.
  • @Repository: 개발자가 직접 구현체를 작성해야 합니다.
@Mapper
public interface UserMapper {
    // MyBatis가 구현체를 자동 생성
}

@Repository
public class UserRepository {
    // 개발자가 직접 구현
}

XML 매핑 사용

@Mapper 인터페이스와 XML 매핑 파일을 함께 사용할 수 있습니다:

@Mapper
public interface UserMapper {
    User getUserById(Long id);
    List<User> getAllUsers();
}
<?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="com.example.mapper.UserMapper">
    <select id="getUserById" resultType="com.example.model.User">
        SELECT * FROM users WHERE id = #{id}
    </select>
    <select id="getAllUsers" resultType="com.example.model.User">
        SELECT * FROM users
    </select>
</mapper>

동적 SQL

MyBatis의 강력한 기능 중 하나인 동적 SQL도 @Mapper 인터페이스에서 사용할 수 있습니다:

@Mapper
public interface UserMapper {
    @Select("<script>" +
            "SELECT * FROM users" +
            "<where>" +
            "<if test='name != null'>AND name LIKE #{name}</if>" +
            "<if test='email != null'>AND email = #{email}</if>" +
            "</where>" +
            "</script>")
    List<User> findUsers(@Param("name") String name, @Param("email") String email);
}

결과 매핑

복잡한 결과 매핑이 필요한 경우, @Results 어노테이션을 사용할 수 있습니다:

@Mapper
public interface UserMapper {
    @Results(id = "userResultMap", value = {
        @Result(property = "id", column = "user_id"),
        @Result(property = "name", column = "user_name"),
        @Result(property = "email", column = "user_email")
    })
    @Select("SELECT * FROM users WHERE user_id = #{id}")
    User getUserById(Long id);
}

테스트

@Mapper 인터페이스의 테스트는 일반적으로 통합 테스트 형태로 이루어집니다:

@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void getUserById_ShouldReturnUser() {
        User user = userMapper.getUserById(1L);
        assertNotNull(user);
        assertEquals("John Doe", user.getName());
    }
}

베스트 프랙티스

  1. 명확한 네이밍: Mapper 인터페이스와 메서드 이름을 명확하게 지정합니다.
  2. 적절한 패키지 구조: Mapper 인터페이스를 적절한 패키지에 위치시킵니다.
  3. 트랜잭션 관리: 서비스 계층에서 트랜잭션을 관리하고, Mapper는 단일 데이터베이스 작업에 집중합니다.
  4. 동적 SQL 활용: 복잡한 쿼리의 경우 동적 SQL을 활용하여 유연성을 높입니다.
  5. 결과 매핑 최적화: 필요한 경우 @Results를 사용하여 결과 매핑을 최적화합니다.

결론

@Mapper 어노테이션은 MyBatis와 스프링 부트를 효과적으로 통합하는 핵심 요소입니다. 이를 통해 개발자는 데이터베이스 작업을 위한 인터페이스만 정의하면 되고, 실제 구현은 MyBatis가 처리합니다. 이는 코드의 간결성, 유지보수성, 그리고 데이터 액세스 로직의 분리를 촉진하여 효율적인 데이터 액세스 계층 구현을 가능하게 합니다.

연관 포스팅

@Repository

profile
HelloMeow~!

0개의 댓글