객체 지향 언어인 자바의 관계형 데이터베이스 프로그래밍을 좀 더 쉽게 할 수 있게 도와 주는 개발 프레임 워크
자바에서는 jdbc api를 사용해서 데이터베이스에 소통했으나 불편한 점이 많아 mybatis가 등장하였다.
mybatis에서는 테이블에 존재하는 하나의 row를 자바 기준에서의 class로 만들고 Dto라고 부른다. 만약 테이블의 줄이 여러 개라면 클래스에 여러 인스턴스들이 모음의 형태로 있을 것이다. mybatis에서는 각각의 sql 선언문을 xml형태로 저장한다.
이제 실습을 위해 새로운 스프링부트 프로젝트를 생성해서 진행해보자!
전 프로젝트들과 다른 점은 Dependencies에 MyBatis Framework와 MySQL Driver가 추가되었다는 점이다.
MyBatis Framework는 스프링부트 안에 있는 프로그램이 아니기 때문에 추가해주었고 MySQL Driver는 MySQL Driver가 있어야 MyBatis Framework가 실제 서버와 소통을 할 수 있기 때문에 추가하였다. (MyBatis는 데이터베이스와 소통을 하는 도구)
먼저 스프링부트 프로젝트를 생성하면 기본으로 있는 application.properties를 application.yml로 변경한다.
** 본인이 입력했던 username과 password를 잘 기억해서 입력하자.. (이 과정에서 잘못입력하여 오류가 났습니다..ㅠ)
application.properties
이 파일은 스프링부트가 애플리케이션을 구동할 때 자동으로 로딩하는 파일이다.
key - value 형식으로 값을 정의하면 애플리케이션에서 참조하여 사용할 수 있다.
mapper : SQL과 그에 대한 처리를 지정하는 역할을 수행한다. 스프링에서 MyBatis를 사용하는 경우에는 Mapper를 인터페이스(Mapper 인터페이스+어노테이션) 형태와 XML(Mapper XML) 형태로 작성할 수 있다.
dto : 계층 간 데이터 교환을 하기 위해 사용하는 객체. 로직을 가지지 않는 순수한 데이터 객체(getter & setter 만 가진 클래스)이다.
dao : 데이터베이스의 data에 접근하기 위한 객체. DataBase에 접근 하기 위한 로직 & 비지니스 로직을 분리하기 위해 사용한다.
위 사진과 같이 작동할 수 있도록 프로젝트를 작성할 것이다. 따라서 해당하는 패키지와 폴더, 파일들을 먼저 생성한다.
(경로 및 생성해야될 파일들은 밑 사진 참고)
만들어야 될 것들 : mapper.xml, mapper(인터페이스), dao, dto
mapper
mapper패키지 안에는 BoardMapper, PostMapper 인터페이스를 만든다.
mapper.xml
(board-mapper.xml의 경우 4번 째 줄 끝부분이 BoardMapper인 것만 제외하면 post-mapper.xml과 동일하다.)
필요한 파일들을 다 만들었으면 수정해보자!
먼저 post-mapper.xml 부분을 수정한다.
4번째 줄 namespace에 있는 인터페이스와 5번째 줄에 있는 createPost 라는 아이디를 이용해서 5번째줄의 parameterType의 값에 sql문(6~7번째 줄)을 일치시켜 전달해준다는 뜻이다.
그 아래에 있는 select, update, delete문도 마찬가지의 원리라고 생각하면 되는데 반환하는 값이 있는 경우에는 resultType을 기재해주면 된다.
xml 작성을 마쳤다면 이에 맞게 mapper 인터페이스 파일인 PostMapper.java도 수정해보자.
메소드 이름을 createPost, readPost .. 으로 정하고 xml에서 작성한 것에 맞춰 코드를 작성한다.
이제 dao만 작성하면 된다.
SqlSessionFactory란 데이터베이스와의 연결과 SQL의 실행에 대한 모든 것을 가진 객체이다. 내부적으로 SQLSession을 만들어내는데 이 SQLSession을 통해서 Connection을 생성하거나 원하는 SQL을 전달하고 결과를 리턴받는다.
다음으로 create에 해당하는 메소드를 작성해보자.
22번째 줄 - 세션에서 PostMapper와 동일한 구현체를 달라고 하면 PostMapper 인터페이스를 구현한 구현체가 mapper로 주입되게 된다.
21~23번째 줄과 25~29번째 줄(주석 처리된 줄)은 동일한 기능을 하는 코드이다. (21~23줄 같이 작성을 하면 try가 같히는 순간에 세션이 자동으로 close된다.)
왜 매번 SqlSessionFactory에서 세션을 열고 닫고 하지?
mapper 인스턴스는 thread safe하지 않다. 즉 요청이 두 번 연속적으로 들어왔을 때 각 요청이 서로에게 영향을 끼칠 수 있기 때문에 요청이 필요할 때마다 열고 닫는 방식으로 진행하는 것이다.
다 작성을 한 후 간단한 test컴포넌트를 작성해보았다. (원래 이렇게 하는게 아니지만 지금 실력에선 이 test가 최선이다..ㅠ)
콘솔창에서 확인이 가능하고
Mysql 워크벤치에서도 확인이 가능했다.
board-mapper.xml 을 수정한다.
그 다음 BoardMapper.java를 수정한다.
다음으로 BoardDao.java를 수정한다.
그리고 TestComponent.java 파일에 post처럼 private final BoardDao boardDao; 선언을 해주고 아래와 같이 코드를 입력한다.
그러면 따로 id에 대한 설정을 안해도 id가 잘 반환되는 것을 알 수 있다. 이는 useGeneratedKeys, keyProperty로 인해 발생하는 것이다.
useGeneratedKeys : (insert, update에만 적용) 자동생성 키를 받을때 true로 설정한다. (default: false)
keyProperty : 리턴 될 key property 설정. 여러개를 사용한다면 ,(콤마)를 구분자로 나열한다.