이번에는 이전 설정을 활용해서 직접 MyBatis를 활용해보자.
단, 아직 MyBatis를 제대로 공부해보지 않았기 때문에 MyBatis의 기능을 온전히 활용할 수 없다. 따라서 일단 실제로 Query문이 수행되는지 확인하는 쉬운 Query문에 대해 적용해볼 것이다.
일단 MyBatis를 활용하기 위해선 Database와 Table이 존재해야 할 것이다. Table에 대한 Setting은 아래와 같이 설정했다.
@Data
public class Member {
private int num;
private String name;
private String id;
private String pwd;
}
MyBatis에서 중요한 것은 Query문과 연동될 객체를 만드는 과정이다
SQL Mapper라는 것이 객체와 Query문을 연동하는 기술이고 Query문은 우리가 직접 입력해줘야 하기 때문에 결국 Query문과 연동할 객체가 필요하게 될 것이며, 이를 만드는 과정이 가장 먼저 수행되어야 한다.
나중에는 객체의 멤버 변수 이름과 Table Column 이름이 동일하지 않아도 매칭시킬 수 있지만 아직 이 방법은 배우지 않았으므로 일단은 동일하게 설정해 놓자.
Mapper 측에서 자동으로 객체 값을 채울 수 있어야 하기 때문에 @Setter, 멤버 변수에 대한 Setter 함수를 설정해줘야 하며 Query에 멤버 변수 값을 적용하기 위해 @Getter, 멤버 변수에 대한 Getter 함수도 설정해줘야 한다.
따라서 @Getter, @Setter 뿐만이 아닌 객체 간 동일 여부 및 @ToString도 포함한 @Data를 활용했다
@Mapper
public interface UserMapper {
List<Member> findAll();
}
우리는 SqlSessionTempalte이 아닌 MapperInterface 방식을 활용할 것이므로 Mapper Interface를 형성해야 한다.
이 Mapper Interface는 결국 "Query문을 수행시키는 주체"라고 이해하면 된다.
이전에 MyBatis 동작 방식에서도 배웠지만 Application에 온 요청에 따라 필요한 Mapper Interface에 접근하고 이 Mapper Interface가 연동된 XML(Mapping File)에 접근하여 존재하는 Query문을 수행시키는 방식으로 MyBatis가 동작한다.
@Mapper Annotaion만 인터페이스에 달아주면 다른 Annotation도 필요 없고 추가 Setting 방법도 없다. 그저 Mapper Interface 이름을 지정해주고, 해당 Interface 아래에 여러 가지 메서드를 입력시키기만 하면 끝난다. insertMember(Member meber) 메서드처럼 입력값을 받는 메서드도 추가할 수 있다.
결국 Mapper Interface는 Query문이 저장된 XML 파일을 수행시키는 중간 다리 역할이기 때문에 상속받아 구현할 필요는 없다.
// Controller
@RestController
public class UserController {
@Autowired
UserService userService;
@PostMapping(value="/")
public ResponseEntity<?> findAll(){
return new ResponseEntity<>(userService.findAll(), HttpStatus.OK);
}
}
// Serivce
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public List<Member> findAll(){
return userMapper.findAll();
}
}
MVC 패턴 중 Controller와 Service를 생성하는 과정이다. UserMapper를 활용하기 위한 Setting에 불과하므로 큰 의미는 두지 않아도 된다.
원래 생성자 주입이 가장 좋지만, Query문 수행 여부만 확인하기 위해 만든 것이므로 필드 주입을 활용했다.
이 부분이 핵심이 아닐까 싶다. 먼저 우리는 mapper-locatoins를 "classpath:/egovframework/sqlmap/mysql/*/.xml"로 지정했다. 즉, mapper.xml은 "resources/egovframework/sqlmap/mysql" 패키지 아래에만 존재하면 무조건 Mapper Interface가 인식 가능한 XML이 된다는 것이다.
필자는 아래 사진과 같이 mapper.xml 파일을 저장했다.
mapper.xml 파일은 아래와 같다
<?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="egovframework.com.review.mybatis.UserMapper">
<select id="findAll" resultType="Member">
select * from member
</select>
</mapper>
재밌는 부분이 많다. 하나씩 살펴보자.
MyBatis를 활용하기 위한 설정값 및 함수를 가져오는 부분이므로 Default로 추가시켜주자
어떤 Mapper Interface와 연결되어 있는지를 명시해주는 것이다.
우리는 UserMapper 클래스가 mapper.xml과 연동되길 원하므로 UserMapper의 Path를 namespace로 지정해줌으로써 "UserMapper Interface가 mapper.xml을 통해 Query를 실행한다"라는 것을 Applicatoin 측에 알려주는 것이다.
< mapper>와 < /mapper> 사이에 namespace로 지정한 Mapper Interface에 존재하는 메서드에 대한 Query문들을 입력하는 것이다.
namespace에 지정한 Mapper Interface 메서드에 Query를 할당해주는 방법이다.
id는 메서드 이름이다. UserMapper Interface에서 findAll() 메서드가 호출될 때 여러 구문중 id="findAll"으로 지정된 구문을 찾게 된다. <select id="findAll">
으로 지정되었기 때문에 해당 구문이 UserMapper의 findAll() 메서드와 연결되는 것이고, 구문 내에 존재하는 select * from member
Query문을 수행하는 것이다.
resultType은 Query를 통해 도출된 결과를 Member라는 객체 형태로 저장해서 반환함을 명시해준다. 이때 MyBatis는 결과가 여러 개일 경우 resultType으로 List를 만들어 반환하게 된다.
나중에 자세히 배우겠지만 일단 이 정도로만 알고 넘어가자.
즉, UserMapper에 있는 findAll()이라는 메서드를 수행하면 id="findAll"에 지정된 Query문이 실행된다. 그리고 이 Query문의 결과는 resultType으로 지정된 Member 객체 형태로 반환된다. 이때 Member 객체 여러 개가 반환되면 알아서 List형식에 담아 반환한다.
실행해야 할 Query는 select * from member
이다. 즉 member Table에 존재하는 모든 데이터를 Member 객체 형태에 담아 반환하고, 값이 여러 개일 경우 List에 담아 반환한다 라는 의미를 가지는 Query이자 메서드가 완성되는 것이다.
DB에 존재하는 데이터를 모두 가지고 왔음을 알 수 있다. 즉, 제대로 Query문이 실행이 된 것이다.
이제 앞에서 설정한 MyBatis에 대한 설정값이 제대로 적용되었음을 확신할 수 있다. 이제는 MyBatis 활용법에 대해 제대로 알아보자.
MyBatis를 활용하다 보면 가장 어려운 점이 이 점인 것 같다.
"이 Mapper Interface는 어떤 XML과 연동되어 있을까?"
항상 Mapper Interface와 연동된 XML을 찾기 위해 검색을 통해 알아볼 수는 없는 노릇이다.
이를 쉽게 해결하기 위한 Plugin이 존재하는데, 바로 MyBaitsX이다.
MyBatisX Plugin을 설치하면 IntelliJ 측에서 알아서 Mapper Interface와 XML 파일을 인식하여 자동으로 매핑시켜준다.
MyBatisX를 적용한 이후 Mapper Interface이다.
UserMapper와 findAll() 메서드 옆에 검은색 새 모양이 뜸을 알 수 있다.
Interface에 적용된 새를 클릭하면 Mapper Interface와 연동된 XML 파일로 이동한다.
Method에 적용된 새를 클릭하면 XML 내에 해당 메서드와 연동된 구문 및 Query문으로 이동한다.
메서드와 Mapper Interface 연동 상황을 실시간으로 확인할 수 있으며 Query문에 대한 수정 및 추가가 쉽기 때문에 강력 추천하는 바이다.
(추가가 쉬운 이유 : 만약 추가가 안 되었을 경우 옆에 새 모양이 뜨지 않기 때문에 해당 메서드와 연동될 구문이 추가되지 않았음을 빠르게 인지할 수 있음)
추가로 mapper.xml 파일 내에서도 이런 새 버튼이 연동되어 연결된 Mapper Interface 및 Method로 바로 이동할 수 있다.