본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 47일차 (2023-07-27) 자바 프로그래밍_52. Mybatis SQL-mapper 프레임워크 사용하기_Board_개인프로젝트 - 마트 관리 시스템

by prometedor 2023. 7. 27.
## 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

https://mybatis.org/

 

mybatis

 

mybatis.org

=>

ㄴ 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 – MyBatis 3 | Getting started

It's very important to understand the various scopes and lifecycles classes we've discussed so far. Using them incorrectly can cause severe concurrency problems. Dependency Injection frameworks can create thread safe, transactional SqlSessions and mappers

mybatis.org

=>

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 추가해주기