@Repository vs @Interface 그리고 Mybatis
시작하기 전 ...
기존 프로젝트 구조는 항상 Controller.java - Service.java - DAO.java - Mapper.xml 의 구조를 사용하였으며
DAOImpl의 구현 클래스에서 @Repository 어노테이션을 사용하여 해당 클래스가 Database와 통신하는 클래스임을 약속하였다.
하지만, Controller.java - Service.java - Mapper.java - Mapper.xml의 구조가 될 수도 있음을 알게되었다.
그럼 언제 어떻게 사용하는지, 무엇이 다른지 살펴보자!
Goal
- Mybatis를 사용하는 이유를 이해한다.
- @Repository vs @Mapper 언제, 왜 사용하고 어떻게 다른지를 이해한다
각각의 Layer
- 프레젠테이션 계층 (Presentation layer) - UI 계층 (UI layer)
- 애플리케이션 계층 (Application layer) - 서비스 계층 (Service layer)
- 비즈니스 논리 계층 (Business logic layer) - 도메인 계층 (Domain layer)
- 데이터 접근 계층 (Data access layer) - 영속 계층 (Persistence layer)
여기서, DB와 통신을 하는 Persistent layer를 살펴보자.
Persistent layer
- Persistence Layer에서 개발하는 Framework
- jdbc 프로그래밍에 비해 간단한 작업만으로 데이터베이스와의 연동과 개발 보장한다.
- dbms에 대한 종속성이 줄어든다. 유지보수가 쉬우며 직관적이다.
- Framework는 sql Mapper와 orm으로 구성되어 있다.
- sql Mapper와는 다르게 orm은 관계형구조를 가지며 sql mapper는 쿼리으로 동작하지만 orm은 메서드로 데이터를 조작할 수 있다.
Mybatis
- Mybaits는 자바 Object와 SQL 사이를 자동으로 매핑해주는 기능을 지원하는 영속성(Persistence) 프레임워크이다.
- 해당 코드는 map 인터페이스와 매핑을 위한 xml과 annotation을 사용한다.
Mybatis의 장점
- 관심사를 분리하므로써, 유지보수성을 높이고 코드의 간결하게 함
- jdbc로 처리하는 코드의 설정(Connection) 부분을 줄이고 실제 sql문에 연결함으로서 빠른 개발이 가능
(Connection, PreparedStatement, ResultSet)
- jdbc로 처리하는 코드의 설정(Connection) 부분을 줄이고 실제 sql문에 연결함으로서 빠른 개발이 가능
- 성능과 생산성
- sql에 변경이 있을 때마다 자바 코드를 수정하거나 컴파일할 필요가 없다.
- 데이터 접근 속도를 높여주는 Join 매핑(구조적 강점) , SQL를 직접작성하므로 최적화된 쿼리 구현가능
- 도메인 객체나 VO객체 중심으로 개발이 가능하다
Mybatis의 단점
- 테이블이 변경되고 DTO가 변경될 때마다 매핑에 대한 부분을 다시 수정해야하는 번거로움이 존재한다.
- 위와 같은 이유로 어플리케이션과 데이터베이스간의 설계에 대한 부분을 수정해야하는 경우 많은 설정이 바뀌어야 한다.
- 런타임을 해야 오류를 확인할 수 있다.
- 데이터베이스 변경시 로직도 함께 수정해야한다.
=> 추후 JPA은 Mybatis의 이런 단점을 극복하고자 사용됨.
그럼 어떻게 Mybatis가 스프링의 xml과 mapping이 되는 것인가?
Mybatis를 사용하려면 크게 4가지를 정의해야 한다.
- 쿼리문을 정의한 mapper.xml 파일
- Mapper.xml를 java코드에서 실행시키는 Mapper Class or interface (Mapper.java)
- 쿼리의 결과데이터를 담는 중간 매개 Class (보통 VO)
- 위의 3개의 위치를 알려주는 설정
Class를 사용하는 방식과 Interface를 사용하는 방식
Class 방식 DAO
DAO란?
Data Access Object의 약어로 실질적으로 DB에 접근하여 데이터를 조회하거나 조작하는 기능을 전담하는 객체를 말한다.
DAO를 사용하는 이유
- 효율적인 커넥션 관리와 보안성 때문이다.
- DAO는 저수준의 Logic과 고급 비즈니스 Logic을 분리한다.
- domain logic으로부터 DB관련 mechanism을 숨기기 위해 사용한다.
장점
- 쿼리문 실행 전에 넣어줄 매개변수와 쿼리 결과값의 변형을 정의할 수 있다.
- Namespace를 내 마음대로 둘 수 있다.
- .xml 파일의 쿼리문 id와 mapper 메소드명을 일치시킬 필요가 없다.
단점
- Sqlsession 객체를 주입받아야 하며, 쿼리문 실행 시 항상 호출해야 한다.
- 쿼리문 호출 시 sqlsession에 .xml 파일의 namespce와 쿼리문 id를 매개변수로 넘겨야한다.
- 문자열 에러를 런타임 시 알 수 있다.
인터페이스 방식
Mapper인터페이스란?
- Mybatis 매핑XML에 기재된 SQL을 호출하기 위한 인터페이스이다. Mybatis3.0부터 생겼다.
장점
- 메소드의 내부 구현이 불필요하다 => 유지보수 측면에 유리
- Sqlsession 객체 주입이 불필요하다.
- .xml 파일의 쿼리문 id와 mapper 메소드 명이 일치한다.
단점
- .xml의 Namespace가 실제 Mapper.java 위치를 가르켜야 한다.
- 메소드 내부 정의가 불가능하다.
Mapper인터페이스를 사용하는 방법
- Mapper인터페이스는 개발자가 직접 작성한다.
- mapper 네임스페이스는 패키지명을 포함한 인터페이스 명으로 작성한다.
- SQL id는 인터페이스에 정의된 메서드명과 동일하게 작성한다
@Repository vs @Mapper
@Repository
package org.springframework.stereotype;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
@AliasFor(
annotation = Component.class
)
String value() default "";
}
- Spring에서 제공하는 @Repository는 DAO의 의미를 지닌다
- mybatis.xml에서 사용하고 있는 맵핑xml 중 namespace가 value로 지정된 xml을 자동으로 찾는다
@Mapper
package org.apache.ibatis.annotations;
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Mapper {
}
- MyBatis에서 제공하는 @Mapper는 sql mapper의 의미를 지닌다
- MyBatis 3.0부터 지원하는 기능. MyBatis와 같은 ORM(Object Relation Mapping) 프레임워크에서 사용
- Mapper 클래스의 정의를 하며 자동으로 빈을 등록한다
- @Mapper 어노테이션을 선언한 interface를 생성하면 따로 implements(구현) 생략
- @Mapper 어노테이션에 생성한 API의 이름과 MyBatis Mapper에 작성한 Sql ID는 반드시 일치해야 함
참고
http://mybatis.org/spring-boot-starter/mybatis-spring-boot-test-autoconfigure/
https://ddacker.tistory.com/13
https://twofootdog.github.io/Spring-DAO%EC%99%80-Mapper%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90/