id, name, phone, email 컬럼을 가지는 tbl_student 테이블에 대한 CRUD작업
예제를 위해 아래와 같은 간단한 테이블을 만들었다.
PK : Primary Key
NN : NOT NULL
AI : Auto Increase (레코드가 추가될 때 해당 자동 증가된 값이 들어감)
DTO란 Data Trasfer Object로 DB에서 데이터를 불러오거나 저장 할 때, 데이터를 담기위한 그릇이라고 볼 수 있다. 흔히 알고있는 VO(Value Object)와 거의 같은 의미이다.
DB에서 데이터를 조회(SELECT) 했을 때 데이터를 담기 위한 객체이다.
API나 뷰의 종류에 따라 원하는 값만 불러오도록 일부 맴버변수를 제외해도 된다.
예제에서는 Table의 모든 값을 불러오도록 했다.
@Getter : lombok이 제공하는 애너테이션. 맴버변수들의 Getter 매서드를 자동으로 생성해준다.
@Getter
public class ResStudentDto {
private long id;
private String name;
private String phone;
private String email;
}
@Getter : lombok이 제공하는 애너테이션. 맴버변수들의 Getter 매서드를 자동으로 생성해준다.
@Bulder : 안전한 객체 생성을 위한 애너테이션이다. StudentService.java에서 사용 예제를 참고.
@Getter
@Builder
public class ResStudentDto {
private long id;
private String name;
private String phone;
private String email;
}
ReqStudentSaveDto와 거의 같으나 PK인 id는 수정하지 않을 것이므로 맴버변수 id만 없다.
@Getter
@Builder
public class ResStudentDto {
private String name;
private String phone;
private String email;
}
CRUD작업에 사용할 Query를 가지고있는 파일.
'\r\n' 해주는 이유 :
쿼리 내부의 '#{}' 의미 : 쿼리를 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}";
}
StudentSql.java에서 만든 Query들을 실제 Sql Query로 매핑하여 사용 할 수 있게 해주는 인터페이스.
@Mapper : 해당 인터페이스가 Mybatis의 인터페이스임을 명시해주는 애너테이션.
@Option : Query실행 시 일부 옵션을 줄 수 있다.
특히 DB에 Insert후 key값을 다시 자바 로직에서 사용 해야할 때가 있는데 아래와 같이 key값을 가져 올 수 있다.
@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);
}
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기능을 사용 할 수 있다.