본문 바로가기
백엔드/스프링

[Spring] MyBatis 어노테이션 기반 문법

by AI읽어주는남자 2025. 9. 15.
반응형

MyBatis 어노테이션 기반 문법 요약

이 문서는 제공된 BatisMapper.java 예제를 기반으로, 어노테이션을 사용하는 기본 MyBatis 문법을 요약합니다.

1. @Mapper 어노테이션

이 어노테이션은 인터페이스에 선언하여 Spring에게 해당 인터페이스가 MyBatis 매퍼임을 알려주는 역할을 합니다. Spring은 이 인터페이스의 구현체를 자동으로 생성하여 Spring 컨테이너에 등록하며, 다른 컴포넌트에서 의존성 주입(DI)을 통해 사용할 수 있게 해줍니다.

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface BatisMapper {
    // ... 메소드들
}

2. SQL 조작 어노테이션

MyBatis는 SQL 쿼리를 Java 코드에 직접 작성할 수 있도록 여러 어노테이션을 제공합니다.

@Insert

SQL INSERT 구문을 정의할 때 사용합니다. 메소드의 반환 타입은 보통 int로 하며, 이는 삽입된 레코드(행)의 수를 의미합니다.

  • 예시:
    @Insert("insert into student (name, kor, math) values (#{name} , #{kor} , #{math}) ")
    int save( StudentDto studentDto);
  • 파라미터: #{...} 구문은 studentDto 객체의 필드 값에 접근하기 위해 사용됩니다. (예: #{name}studentDto.getName()에 해당합니다.)

@Select

SQL SELECT 구문을 정의할 때 사용합니다. 반환 타입은 쿼리 결과에 맞춰 지정해야 하며, 단일 객체, List, Map 등 다양한 형태가 될 수 있습니다.

  • 예시 (전체 조회):이 쿼리는 student 테이블의 모든 레코드를 반환하며, MyBatis가 각 레코드를 StudentDto 객체에 자동으로 매핑해줍니다.
  • @Select("select * from student") List<StudentDto> findAll();
  • 예시 (개별 조회):#{sno}는 메소드의 파라미터 sno 값을 WHERE 절의 조건으로 사용합니다. 조회 결과는 Map 형태로 반환되며, 여기서 키는 컬럼명, 값은 해당 컬럼의 데이터가 됩니다.
  • @Select("select * from student where sno = #{sno}") Map<String, Object> find(int sno);

@Delete

SQL DELETE 구문을 정의할 때 사용합니다. 보통 삭제된 레코드의 수를 의미하는 int를 반환합니다.

  • 예시:
    @Delete("delete from student where sno = #{sno}")
    int delete(int sno);
  • 파라미터: 기본 자료형 파라미터 sno#{sno} 형태로 직접 참조됩니다.

@Update

SQL UPDATE 구문을 정의할 때 사용합니다. 이 역시 보통 수정된 레코드의 수를 의미하는 int를 반환합니다.

  • 예시:
    @Update("update student set name = #{name} , kor = #{kor} , math = #{math} where sno = #{sno}")
    int update(StudentDto studentDto);
  • 파라미터: @Insert 예시와 마찬가지로, studentDto 객체의 필드 값들이 수정할 데이터로 사용됩니다.

3. #{}를 이용한 파라미터 매핑

#{} 구문은 MyBatis에서 SQL 쿼리로 파라미터를 전달하는 표준 방식입니다. 이 방식은 내부적으로 PreparedStatement를 사용하여 SQL 인젝션 공격을 방지하므로 안전합니다.

  • DTO/객체 사용 시: #{필드명}은 해당 객체의 getter 메소드를 호출하여 값을 가져옵니다. (예: #{name}studentDto.getName()을 호출)
  • 기본 자료형(int, String 등) 사용 시: #{파라미터명}은 메소드의 파라미터를 직접 참조합니다. (예: delete 메소드의 #{sno})

 


 

1) Controller

package example.day06;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping ("/day06/batis")
@RequiredArgsConstructor // final 변수에 대해 자동 생성자 만들어줌
public class BatisController {

    // * Mapper 객체 DI
    private final BatisMapper batisMapper;

    // 1. 학생 등록
    // URL : http://localhost:8080/day06/batis
    // BODY : { "name" : "유재슥" , "kor" : 97 , "math" : 86 }
    // RETURN : 1(성공) 0(실패)
    @PostMapping("")
    public ResponseEntity<Integer> save(@RequestBody StudentDto studentDto){
        Integer result = batisMapper.save(studentDto);
        return ResponseEntity.status(200).body(result);
    }


    // 2. 전체 학생 조회
    // URL : http://localhost:8080/day06/batis
    @GetMapping("")
    public ResponseEntity<List<StudentDto>> findAll(){
        // 현재 예제는 서비스를 생략
        List<StudentDto> result = batisMapper.findAll();
        // ResponseEntity 응답객체
        return ResponseEntity.status(200).body(result);
    }

    // 3. 개별 학생 조회
    // URL : http://localhost:8080/day06/batis/find?sno=1
    @GetMapping("/find")
    public ResponseEntity<Map<String , Object>> find(@RequestParam int sno){
        Map<String , Object> result = batisMapper.find(sno);
        return ResponseEntity.status(200).body(result);
    }

    // 4. 개별 학생 삭제
    // URL : http://localhost:8080/day06/batis?sno=1
    // RETURN : 1(성공) 0(실패)
    @DeleteMapping("")
    public ResponseEntity<Integer> delete(@RequestParam int sno){
        int result = batisMapper.delete(sno);
        return ResponseEntity.status(200).body(result);
    }

    // 5. 개별 학생 수정
    // URL : http://localhost:8080/day06/batis
    // BODY : { "sno" : 2 , "name" : "유재슥" , "kor" : 97 , "math" : 86 }
    // RETURN : 1(성공) 0(실패)
    @PutMapping("")
    public ResponseEntity<Integer> update(@RequestBody StudentDto studentDto){
        Integer result = batisMapper.update(studentDto);
        return ResponseEntity.ok(result); // ok는 200번
    }


} // class end

 

2) Mapper

package example.day06;

import org.apache.ibatis.annotations.*;

import java.util.List;
import java.util.Map;

@Mapper // 해당 인터페이스를 마이바티스(스프링 컨테이너)에 등록, DAO 역할 대신
public interface BatisMapper {

    // 1. 학생 등록 : ? 대신에 #{매개변수} 들어감
    @Insert("insert into student (name, kor, math) values (#{name} , #{kor} , #{math}) ")
    int save( StudentDto studentDto); // 추상메소드
        // int : insert된 레코드 수를 반환 , 1 : 성공 , 0 실패

    // 2. 전체 학생 조회
    @Select("select * from student")
    List< StudentDto > findAll();
    
    // 3. 개별 학생 조회 (Map 테스트)
    @Select("select * from student where sno = #{sno}")
    Map< String , Object > find(int sno);
    
    // 4. 개별 학생 삭제
    @Delete("delete from student where sno = #{sno}")
    int delete( int sno ); // 추상메소드

    // 5. 개별 학생 수정
    @Update("update student set name = #{name} , kor = #{kor} , math = #{math} where sno = #{sno}")
    int update( StudentDto studentDto );


} // inter end

 

3) Dto 

package example.day06;

import lombok.*;

@Data @Builder
@NoArgsConstructor @AllArgsConstructor
public class StudentDto {
    private int sno;
    private String name;
    private int kor;
    private int math;
}

 

3) SQL 

DROP DATABASE IF EXISTS springweb2;
CREATE DATABASE springweb2;
USE springweb2;

-- --------------------------------------- 실습1 ----------------------------------------
CREATE TABLE products (
    product_id INT PRIMARY KEY AUTO_INCREMENT, -- 상품 ID (자동 증가)
    product_name VARCHAR(255) NOT NULL,        -- 상품명
    stock_quantity INT NOT NULL                -- 재고 수량
);

INSERT INTO products (product_name, stock_quantity) VALUES
('무선 이어폰', 25),
('스마트워치', 12),
('게이밍 키보드', 30),
('기계식 마우스', 8),
('휴대용 충전기', 15);


-- --------------------------------------- day06 example ----------------------------------------
-- 학생 테이블
CREATE TABLE student (
    sno INT AUTO_INCREMENT,              -- 학생 번호 (자동 증가)
    name VARCHAR(50) NOT NULL,           -- 이름
    kor INT NOT NULL,                    -- 국어 점수
    math INT NOT NULL,                    -- 수학 점수
    CONSTRAINT  PRIMARY KEY (sno)  -- 기본키 제약 조건 추가
);

INSERT INTO student (name, kor, math) VALUES ('홍길동', 85, 90);
INSERT INTO student (name, kor, math) VALUES ('김철수', 78, 88);
INSERT INTO student (name, kor, math) VALUES ('이영희', 92, 95);
INSERT INTO student (name, kor, math) VALUES ('박지민', 70, 65);
INSERT INTO student (name, kor, math) VALUES ('최유리', 88, 82);

select * from student;
반응형