Mybatis를 이용한 CRUD

Yebali·2020년 12월 4일
0

약간의_Spring

목록 보기
2/30

Mybatis를 이용한 간단한 CRUD 예제

id, name, phone, email 컬럼을 가지는 tbl_student 테이블에 대한 CRUD작업

1. DB 테이블

예제를 위해 아래와 같은 간단한 테이블을 만들었다.
PK : Primary Key
NN : NOT NULL
AI : Auto Increase (레코드가 추가될 때 해당 자동 증가된 값이 들어감)

2. DTO 객체

DTO란 Data Trasfer Object로 DB에서 데이터를 불러오거나 저장 할 때, 데이터를 담기위한 그릇이라고 볼 수 있다. 흔히 알고있는 VO(Value Object)와 거의 같은 의미이다.

2.1 ResStudentDto.java

DB에서 데이터를 조회(SELECT) 했을 때 데이터를 담기 위한 객체이다.
API나 뷰의 종류에 따라 원하는 값만 불러오도록 일부 맴버변수를 제외해도 된다.
예제에서는 Table의 모든 값을 불러오도록 했다.

@Getter : lombok이 제공하는 애너테이션. 맴버변수들의 Getter 매서드를 자동으로 생성해준다.

@Getter
public class ResStudentDto {
    private long id;

    private String name;

    private String phone;
    
    private String email;
}

2.2 ReqStudentSaveDto.java

@Getter : lombok이 제공하는 애너테이션. 맴버변수들의 Getter 매서드를 자동으로 생성해준다.
@Bulder : 안전한 객체 생성을 위한 애너테이션이다. StudentService.java에서 사용 예제를 참고.

@Getter
@Builder
public class ResStudentDto {
    private long id;

    private String name;

    private String phone;
    
    private String email;
}

2.3 ReqStudentUpdateDto.java

ReqStudentSaveDto와 거의 같으나 PK인 id는 수정하지 않을 것이므로 맴버변수 id만 없다.

@Getter
@Builder
public class ResStudentDto {
    private String name;

    private String phone;
    
    private String email;
}

3. StudentSql.java

CRUD작업에 사용할 Query를 가지고있는 파일.

'\r\n' 해주는 이유 :

  1. 스트링을 '+' 연산으로 붙일 경우 Query의 키워드 간 공백이 없어 에러가 날 수 있다.
  2. 나중에 디버깅 할 때 쿼리를 보기 편하게 하기 위해서.

쿼리 내부의 '#{}' 의미 : 쿼리를 Mapper 인터페이스에서 사용할 때 @Param 애너테이션을 통해 맵핑 될 값 or Dto객체의 맴버변수가 맵핑 될 값.

public class StudentSql {
	public static final String FIND_ALL_STUDENT = 
    		"SELECT id, name, phone, emeil FROM tbl_student";
            	// 모든 컬럼 값을 원할 경우'SELECT * FROM tbl_student' 사용해도 무관하다.
	
    	public static final String SAVE_STUDENT = 
        	"INSERT INTO tbl_student(id, name, phone, email)\r\n" + 
            	"VALUES(#{id}, #{name}, #{phone}, #{email})";
                // Insert 시 PK값 (id)를 주지 않는다면 Duplicate entry '0' for key 'PRIMARY' 에러가 날 수 있다.
    	
    	public static final String UPDATE_STUDENT = 
        	"UPDATE tbl_student\r\n" + 
            	"SET name=#{name}, phone=#{phone}, email=#{email}\r\n" +
                "WHERE id = #{id}\r\n";
    
    	public static final String DELETE_STUDENT = 
        	"DELETE FROM tbl_student WHERE id = #{id}";
           
}

4. StudentMapper.java (Interface)

StudentSql.java에서 만든 Query들을 실제 Sql Query로 매핑하여 사용 할 수 있게 해주는 인터페이스.

@Mapper : 해당 인터페이스가 Mybatis의 인터페이스임을 명시해주는 애너테이션.
@Option : Query실행 시 일부 옵션을 줄 수 있다.
특히 DB에 Insert후 key값을 다시 자바 로직에서 사용 해야할 때가 있는데 아래와 같이 key값을 가져 올 수 있다.

  1. useGeneratedKeys : DB에서 새로운 레코드 생성 시 auto increase되는 값을 사용할지 여부를 나타내는 옵션
  2. keyProperty : auto increase되는 컬럼이 어떤 컬럼인지 나타내는 옵션
@Mapper
public interface StudentMapper {
	@Select(StudentSql.FIND_ALL_STUDENT)
    	List<ResStudentDto> findAllStudent();
        
        @Insert(StudentSql.SAVE_STUDENT)
        @Options(useGeneratedKeys = true, keyProperty = "id")
        // #{}값들이 ReqStudentSaveDto 내부의 맴버변수 값들로 자동 매핑됨.
        void saveStudent(ReqStudentSaveDto reqestDto);
        /*
        #{}값이 어떤 값인지 일일히 명시해 줌. 두 방법중 편한걸 사용.
        void saveStudent(@Param("id") long id,
        		 @Param("name") String name,
        		 @Param("phone") String phone,
        		 @Param("email") String email)
         */
         
         @Update(StudentSql.UPDATE_STUDENT)
    	void updateStudent(ReqAuthKeyUpdateDto dto);
        
        @Delete(StudentSql.DELETE_STUDENT)
        void deleteStudent(@Param("id") long id);
}

5. StudentService.java

tbl_student Table의 CRUD작업을 담당하는 서비스 객체.

@Service : 서비스레이어, 비지니스 로직을 가진 객체에 사용하는 애터네이션

@Service
public class StudentService {
	@Autowired
    	StudentMapper studentMapper;
    
    	List<ResStudentDto> findAllStudent() {
        	List<ResStudentDto> students = studentMapper.findAllStudent();
            	
                //JPA의 경우 SELECT결과가 없으면 자동으로 빈 ResStudentDto 객체를 반환하지만 
                //Mybatis는 그렇지 않으므로 null을 반환하지 않도록 처리해준다.
            	return studentd != null ? students : new ArrayList<>()
        }
        
        //보통 아래와 같이 ReqStudentSaveDto객체에 담아서 전달 받지만 Builder사용을 보여주기 위해 각각의 값으로 받음.
        //void saveStudent(ReqStudentSaveDto requestDto) {...}
        void saveStudent(String name, String phone, String email) {
        	//@Builder사용 시 아래와 같이 안전한 객체 생성이 가능함.
        	ReqStudentSaveDto requestDto = ReqStudentSaveDto.buider()
            							.name(name)
            							.phone(phone)
            							.email(email)
            							.build();
                                        
           	studentMapper.saveStudent(requestDto);
        }
        
        void updateStudent(ReqStudentUpdateDto requestDto) {
        	studentMapper.updateStudent(requestDto);
        }
    
    	viud deleteStudent(long id) {
        	studentMapper.deleteStudent(id);
        }
}

위의 코드들이 완성되었다면 Controller에서 StudentService Bean을 이용해 tbl_student에 CRUD기능을 사용 할 수 있다.

profile
머리에 다 안들어가서 글로 적는 중

0개의 댓글