## 52. Mybatis SQL-mapper 프레임워크 사용하기
- mybatis 프레임워크의 구동 원리 및 사용법
ㄴ MySQLBoardDao.java, MySQLItemDao.java, MySQLMemberDao.java 파일을 bitcamp.report.dao 패키지로 이동시킴
ㄴ 드래그 & 드랍
=>
=>
ㄴ bitcamp-study > report > app-server > src > main 위치에 resources 폴더 추가
ㄴ bitcamp-study > report > app-server > src > test 위치에 resources 폴더 추가
=>
ㄴ gradle 재설정
=>
=>
ㄴ 이 폴더들 git 에 커밋할 때 빈 폴더여서 커밋이 안됐었음
=> 임의의 파일을 생성해주자 ex) README 파일 추가
ㄴ bitcamp.report.dao 라는 패키지를 생성
ㄴ src/test/resources 위치에 README.md 파일 생성
README.md
ㄴ Markdown Source 클릭하면 글 작성 가능
ㄴ src/main/resources 위치에 있는 bitcamp.report.dao 패키지에 MySQLBoardDao.xml 파일 생성
MyBatis
=>
ㄴ Github Project
ㄴ mybatis-3
ㄴ See the docs
ㄴ Getting Started
=>
MySQLBoardDao.xml
ㄴ <?xml version="1.0" encoding="UTF-8" ?> => xml 선언 부분
MySQLBoardDao.xml
=>
ㄴ mybatis-3-mapper.dtd 파일 다운로드 됨
=>
ㄴ Visual Studio Code 로 해당 파일 열어보기
=>
ㄴ MySQLBoardDao -> BoardDao 로 이름 변경
=>
BoardDao.xml
ㄴ bitcamp.report.dao.mysql 패키지 생성
ㄴ BoardDao.xml 파일을 bitcamp.report.dao.mysql 패키지 로 이동시킴
BoardDao.xml
ㄴ namespace 값을 bitcamp.report.dao.BoardDao 로 줌
BoardDao.java
=>
BoardDao.java
=>
BoardDao.java
ㄴ list -> findAll 로 이름 변경
MySQLBoardDao.java
ㄴ 해당 sql 잘라내기
=>
BoardDao.xml
ㄴ insert 문 넣기
ㄴ sql 넣을 때 "",+ 모두 제거
=>
BoardDao.xml
BoardDao.xml
BoardDao.xml
ㄴ parameterType 에 "bitcamp.report.vo.Board" 입력
BoardDao.xml
ㄴ password 는 필요 없으므로 제거
ㄴ 나머지는 #{...} 로 감싸기
ㄴ {} 안에 값은 프로퍼티 값
BoardDao.xml
ㄴ 필요 없는 코드 제거
Mybatis 라이브러리 다운로드
=>
=>
build.gradle
ㄴ build.gradle 스크립트 파일에 dependencies 부분에 Mybatis 라이브러리 추가
ㄴ gradle 재설정
=>
=>
MySQLBoardDao.java
ㄴ 이제 라이브러리를 인식함
MySQLBoardDao.java
ㄴ SqlSessionFactory 이용
MySQLBoardDao.java
ㄴ SqlSessionFactory는 MyBatis의 핵심 클래스로, 데이터베이스와의 연결을 설정하고 관리함
=> 이 객체를 통해 SqlSession 객체를 생성함
ㄴ SqlSession은 데이터베이스와의 실제 세션을 나타내며, SQL 문 실행, 커밋, 롤백 등의 데이터베이스 작업을 수행하는 데 사용됨
ㄴ 하나의 SqlSession 객체는 하나의 데이터베이스 연결에 해당하며, 사용이 끝나면 닫아야 함
MySQLBoardDao.java
ㄴ SqlSession 의 insert 메서드를 이용
MySQLBoardDao.java
=>
MySQLBoardDao.java
ㄴ 해당 코드 제거해도 됨
MySQLBoardDao.java
ㄴ Board 객체의 category 속성을 DAO의 category 값으로 설정
ㄴ src/main/resources 위치에 mybatis-config 라는 이름의 xml 파일을 생성
ㄴ src/main/resources 위치에 bitcamp.report.config 패키지 생성
=>
ㄴ mybatis-config.xml 파일을 bitcamp.report.config 패키지로 이동
https://mybatis.org/mybatis-3/getting-started.html
=>
mybatis-config.xml
=>
mybatis-config.xml
ㄴ <mappers> 요소 내에 <mapper> 요소로 bitcamp/report/dao/mysql/BoardDao.xml 파일이 지정
=> BoardDao.xml이라는 매퍼 파일을 사용한다는 것을 의미함
=>
mybatis-config.xml
ㄴ 드라이버 위치, JDBC URL, DB 사용자명, 사용자 암호를 정의해둠
ServerApp.java
=>
ServerApp.java
=>
ServerApp.java
ㄴ mybatis 설정 파일을 읽어들일 도구를 준비
ServerApp.java
ㄴ SqlSessionFactory를 만들어줄 빌더 객체 준비
ServerApp.java
ㄴ 빌더 객체를 통해 SqlSessionFactory를 생성
ServerApp.java
=>
ServerApp.java
ServerApp.java
ㄴ 생성자에 sqlSessionFactory 를 추가적으로 받도록 함
BoardAddListener.java
ㄴ SqlSessionFactory 를 이용하기 위해 필드와 생성자에 추가
BoardAddListener.java
ㄴ sqlSessionFactory 는 getConnection 이 아닌 openSession 을 이용함
ServerApp.java
ㄴ ds(DataSource) 대신 sqlSessionFactory(SqlSessionFactory) 를 생성자에 넘겨주도록 함
ㄴ 데이터 추가 테스트 시 제대로 등록되지 않음을 확인
MySQLBoardDao.java
ㄴ sqlSession.commit() 을 통해 커밋을 하도록 해보기
ㄴ 입력했던 데이터 노출되지 않음
ㄴ 실제 데이터베이스에는 노출되고있음
=>
MySQLBoardDao.java
ㄴ MySQLBoardDao 에서는 commit 하지 않도록 하자
ㄴ report-server 프로젝트의 util 패키지에 SqlSessionFactoryProxy 라는 이름의 클래스를 생성
SqlSessionFactoryProxy.java
ㄴ SqlSessionFactory 를 대신하여 특정 작업을 수행하도록 하는 sqlSessionFactoryProxy 라는 클래스를 작성
SqlSessionFactoryProxy.java
=>
SqlSessionFactoryProxy.java
ㄴ SqlSessionFactory 타입 필드와 생성자가 선언되어있지 않아서 발생하는 경고
=>
SqlSessionFactoryProxy.java
=>
SqlSessionFactoryProxy.java
=>
SqlSessionFactoryProxy.java
ㄴ 특정 작업이나 책임을 다른 객체나 메서드에게 위임하도록 하는 Generate Delegate Methods... 를 선택
ㄴ [Select All] 선택하여 모든 메서드 위임하도록 함
SqlSessionFactoryProxy.java
ㄴ ThreadLocal<SqlSession> 은 Java의 ThreadLocal 클래스를 활용하여 SqlSession 객체를 스레드 별로 보관하는데 사용되는 타입임
SqlSessionFactoryProxy.java
ㄴ수동 커밋으로 동작하는 SqlSession 을 원하면 여러 데이터 변경 작업을 묶어서 다루도록 함
ㄴ 스레드에 보관된 SqlSession 객체를 꺼내도록 함
SqlSessionFactoryProxy.java
ㄴ 아직 스레드에 보관된 객체가 없다면 새로 만들어 보관하도록 함
SqlSessionFactoryProxy.java
ㄴ 스레드에 보관된 SqlSession 객체를 리턴하도록 함
ServerApp.java
ㄴ 빌더 객체를 SqlSessionFactoryProxy 의 생성자에 넘겨주도록 함
ㄴ 입력한 데이터가 제대로 추가되어 목록에 출력됨을 확인
ㄴ 실제 데이터베이스에도 제대로 추가됨을 확인
SqlSessionFactoryProxy.java
ㄴ 새로운 메서드 추가
=> sqlSessionBox 에서 꺼내온 sqlSession 값이 null 이라면 rollback 을 해주고, 해당 sqlSessionBox 를 초기화 시키도록 함
ServerApp.java
ㄴ finally 문에서 현재 스레드에 보관된 Connection 객체를 닫고, 스레드에서 제거하도록 해줌
ㄴ SqlSessionFactoryProxy 클래스의 clean() 메서드를 호출하도록 함
BoardDao.xml
ㄴ select 추가
MySQLBoardDao.java
ㄴ 해당 sql 문 잘라내기
=>
BoardDao.xml
ㄴ parameterType 은 int
ㄴ 해당 위치에 잘라낸 sql 문 붙여넣기
ㄴ in-parameter 는 #{...} 으로 나타냄 => 이름은 아무렇게나 지어도 되지만 의미있는 이름으로 지어주도록 하자
MySQLBoardDao.java
ㄴ 해당 주석 부분 모두 제거
MySQLBoardDao.java
ㄴ sqlSessionFactory 의 openSession 을 이용하여 자동커밋을 false 로 정해주고 category 번호를 받아서 리스트를 출력하도록 함
MySQLBoardDao.java
ㄴ 해당 코드 모두 제거
ㄴ 테스트 시 해당 예외 발생
BoardListListener.java
ㄴ 테스트 하기 위해 주석 처리
=>
ㄴ 제목과 작성자를 제외하고 번호와 조회수가 모두 0으로 출력되는 문제 발생
BoardListListener.java
ㄴ board_no, view_count, created_date 컬럼들을 각각 별명을 붙여줌
BoardListListener.java
ㄴ createdDate 는 주석을 풀어주기
ㄴ 번호와 조회수, 등록일 모두 잘 출력됨을 확인
BoardDao.xml
ㄴ findAll 을 그대로 복사해서 붙여넣고 id 를 findBy 로 설정한 후 parameter 타입은 map 으로 설정해주기
BoardDao.xml
ㄴ findBy 는 상세조회이므로 content 컬럼도 추가로 출력하도록 함
BoardDao.xml
ㄴ 번호를 이용해 조회를 하므로 where 절에 board_no 도 추가해주기
BoardDao.xml
ㄴ <resultMap> 요소는 쿼리 결과를 자바 객체로 매핑하기 위해 resultMap 추가하여 사용
BoardDao.xml
=>
BoardDao.xml
ㄴ result 요소는 쿼리 결과와 자바 객체의 필드 간에 명시적인 매핑을 지정하는 역할을 함
ㄴ column: 쿼리 결과에서 어떤 컬럼과 매핑할지를 지정함
ㄴ property: 매핑할 자바 객체의 필드를 지정함
BoardDao.xml
ㄴ bitcamp.report.vo.Board 클래스의 각 필드들이 쿼리 결과의 해당 컬럼들과 매핑되도록 함
BoardDao.xml
=>
BoardDao.xml
=>
BoardDao.xml
=>
BoardDao.xml
ㄴ 보통 primary key 는 result 대신 id 라는 요소를 사용함
=>
BoardDao.xml
ㄴ 결과 레코드의 컬럼 값을 자바 객체에 어떻게 담을 것인지 설정 완료
BoardListListener.java
ㄴ 이제 writer 도 주석 풀어주고 확인하기
=>
ㄴ 예외 발생함을 확인
BoardDao.xml
ㄴ parameterTyep 을 map 으로 설정하고 resultType 이 아닌 resultMap 을 boardMap 으로 설정해주기
ㄴ boardMap 이라는 설정을 만들어놓고 주어주질 않아서 예외가 발생했던 것
=>
=>
BoardDao.xml
ㄴ 주어줬던 별칭 제거해야 함
=>
ㄴ 모든 컬럼 값들이 잘 출력됨을 확인
MySQLBoardDao.java
ㄴ findAll 에서 복사해와서 Map 에 categoryNo 와 boardNo 를 담도록 함
=>
MySQLBoardDao.java
ㄴ categoryNo 와 boardNo 를 담은 맵 객체 paramMap 을 sqlSession 의 selectOne 에 넘겨주도록 함
MySQLBoardDao.java
ㄴ 해당 코드는 모두 제거
=>
ㄴ 테스트 시 정상적으로 출력됨을 확인할 수 있음
=> 그러나 조회수가 증가하지 않는 문제가 발생
MySQLBoardDao.java
ㄴ updateCount 라는 인터페이스 추가
MySQLBoardDao.java
ㄴ insert 메서드를 통째로 복사해서 리턴값을 int 로 변경하고, 메서드 이름은 UpdateCount 로 변경해주도록 함
ㄴ insert -> update
BoardDao.xml
=>
BoardDao.xml
ㄴ updateCount 의 sql 작성하기
BoardDetailListener.java
ㄴ SqlSessioinFactory 이용하도록 함
BoardDetailListener.java
ㄴ viewCount 를 1 증가시키고 이에 대해 updateCount 를 실행하고 제대로 실행됐다면 commit 해주기
ㄴ 예외가 발생한다면 rollback 해주기
BoardAddListener.java
ㄴ sqlSessionFactory.openSession(false).rollback(); 에서 발생하는 오류는 생각할 필요 없으므로 예외 처리문 하나 삭제함
ServerApp.java
ㄴ BoardDetailListener 의 생성자에도 sqlSessionFactory 를 넘겨주도록 함
=>
ㄴ 조회 테스트 시 조회수 증가 확인
Update 구현
BoardDao.xml
MySQLBoardDao.xml
BoardUpdateListener.java
Delete 구현
BoardDao.xml
MySQLBoardDao.java
BoardDeleteListener.java
마무리
ServerApp.java
ㄴ BoardUpdateListener 와 BoardDeleteListener 의 생성자에도 sqlSessionFactory 추가해주기