스프링

MyBatis

코딩 화이팅 2023. 4. 19. 14:48
  • SQL 매핑 프레임워크
  • SQL문과 저장프로시저 등의 매핑을 지원하는 퍼시스턴스 프레임워크
  • JDBC로 처리하는 상당 부분의 코드와 파라미터 설정 및 결과 처리를 대신해준다.
  • Map인터페이스 그리고 자바 POJO를 설정 데이터베이스와 매핑해서 사용할 수 있다.
  • XML과 Annoatation 설정을 통해 사용할 수 있다.

Mybatis 구성

환경 설정 파일

  • MyBatis 전반에 걸친 세팅
  • DB접속 정보 모델 클래스 정보, 매핑정보

Mapper

사용할 SQL문 정의

Mapped Statement

  • SqlSession빌드 및 사용
  • SQL문 실행

Input/Output

  • SQL 실행 시 필요한 데이터
  • SQL 실행결과

SqlSessionFactory

  • 모든 마이바티스 애플리케이션은 SqlSessionFactory 인스턴스를 사용한다.
  • SqlSessionFactory는 SqlSession을 만든다.

SqlSession

데이터베이스에 대해 SQL 명령어를 실행하기 위한 메서드를 포함한다.

MyBatis 설정하기(XML 파일 구조)

밑에 순서대로 설정해줘야됨(굵은 글씨는 필수적 설정)

  • configuration
    • properties
    • settings
    • typeAliases
    • typeHandlers
    • objectFactory
    • plugins
    • environments
      • environment
        • transactionManager
        • dataSource
    • databaseIdProvider
    • mappers

MyBatis 설정하기

mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${driver}" />
				<property name="url" value="${url}" />
				<property name="username" value="${username}" />
				<property name="password" value="${password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="mapper/boardMapper.xml" />
	</mappers>
</configuration>

properties를 사용하여 외부에서 데이터 불러오기

db.proerties
url=jdbc:mysql://localhost:3306/ssafy_board?serverTimezone=UTC
driver=com.mysql.cj.jdbc.Driver
username=ssafy
password=ssafy
====================================================================
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<!-- 여기서 가져와라잉 -->
	<properties resource="config/db.properties"/>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${driver}" />
				<property name="url" value="${url}" />
				<property name="username" value="${username}" />
				<property name="password" value="${password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="mapper/boardMapper.xml" />
	</mappers>
</configuration>

mybatis 설정 파일 가져오기

MyAppSqlConfig.java
package com.ssafy.board.config;

import java.io.IOException;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyAppSqlConfig {
	private static SqlSession session;
	
	static {
		//MyBatis 설정파일을 가져오겠다.
		try {
			String resource = "config/mybatis-config.xml";
			Reader reader = Resources.getResourceAsReader(resource);
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
			//공장도 다 세웠다.
			
			//세션 팩토리르 이용해서 세션을 얻어오겠다.
			session = sqlSessionFactory.openSession(true); //true라는 옵션을 주면 자동으로 커밋이된다.
			System.out.println("세션 생성 성공");
		} catch (IOException e) {
			System.out.println("세션 생성 실패");
		}
	}
	
	//private한 session을 다른 클래스에서도 사용하기 위해서	
	public static SqlSession getSession() {
		return session;
	}	
}

연결해보기

MyAppSqlConfig.java
package com.ssafy.board.config;

import java.io.IOException;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyAppSqlConfig {
	private static SqlSession session;
	
	static {
		//MyBatis 설정파일을 가져오겠다.
		try {
			String resource = "config/mybatis-config.xml";
			Reader reader = Resources.getResourceAsReader(resource);
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
			//공장도 다 세웠다.
			
			//세션 팩토리르 이용해서 세션을 얻어오겠다.
			session = sqlSessionFactory.openSession(true); //true라는 옵션을 주면 자동으로 커밋이된다.
			System.out.println("세션 생성 성공");
		} catch (IOException e) {
			System.out.println("세션 생성 실패");
		}
	}
	
	public static SqlSession getSession() {
		return session;
	}
	
}
====================================================================
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssafy.board.model.dao.BoardDao">
</mapper>
====================================================================
package com.ssafy.board.test;

import com.ssafy.board.config.MyAppSqlConfig;
import com.ssafy.board.model.dao.BoardDao;
import com.ssafy.board.model.dto.Board;

public class Test {
	public static void main(String[] args) {
		BoardDao dao = MyAppSqlConfig.getSession().getMapper(BoardDao.class);
	}
}        
//
세션 생성 성공

MySql과 연결하여 리스트 불러오기

MySql

DROP DATABASE IF EXISTS ssafy_board;
CREATE DATABASE ssafy_board DEFAULT CHARACTER SET utf8mb4;

USE ssafy_board;

CREATE TABLE board (
	id INT AUTO_INCREMENT,
    writer VARCHAR(20) NOT NULL,
    title VARCHAR(50) NOT NULL,
    content TEXT,
    view_cnt INT DEFAULT 0,
    reg_date TIMESTAMP DEFAULT now(),
    PRIMARY KEY(id)
);

INSERT INTO board(title, writer, content) 
VALUES ("BackEnd 너두 마슷허","양씨","너도 할 수 있어"),
	   ("누르지마시오", "따봉맨", "아무내용없음"),
       ("대답잘하는 법", "송소연", "채팅 잘치면됨 네(필쑤)");

SELECT * FROM board;
commit;

java

BoardDao.java
package com.ssafy.board.model.dao;

import java.util.List;

import com.ssafy.board.model.dto.Board;

public interface BoardDao {
	// 전체 게시글을 몽땅 들고 오쎄용
	public List<Board> selectAll();

	// ID에 해당하는 게시글 하나 가져오기
	public Board selectOne(int id);

	// 게시글 등록
	public void insertBoard(Board board);

	// 게시글 삭제
	public void deleteBoard(int id);

	// 게시글 수정
	public void updateBoard(Board board);

	// 조회수 증가
	public void updateViewCnt(int id);

}
=====================================================================
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssafy.board.model.dao.BoardDao">

<!-- 	전체글 조회  -->
	<select id="selectAll" resultType="Board">
<!-- 	resultType안에는 넘겨 받은 거 받을 바구니를 써야됨  -->
		SELECT id, content, writer, title, view_cnt as viewCnt, date_format(reg_date, '%y-%m-%d %H:%i:%s') as regDate
		FROM board;
	</select>
</mapper>
=====================================================================
mybatis-confin.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<!-- 여기서 가져와라잉 -->
	<properties resource="config/db.properties"/>
<!-- 	typeAliases를 사용하여 간단한 아이디를 지정하여 쉽게 불러줄 수 있다. -->
	<typeAliases>
		<typeAlias type="com.ssafy.board.model.dto.Board" alias="Board"/>
	</typeAliases>	
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${driver}" />
				<property name="url" value="${url}" />
				<property name="username" value="${username}" />
				<property name="password" value="${password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="mapper/boardMapper.xml" />
	</mappers>
</configuration>
=====================================================================
package com.ssafy.board.test;

import com.ssafy.board.config.MyAppSqlConfig;
import com.ssafy.board.model.dao.BoardDao;
import com.ssafy.board.model.dto.Board;

public class Test {
	public static void main(String[] args) {
		BoardDao dao = MyAppSqlConfig.getSession().getMapper(BoardDao.class);
		for (Board b : dao.selectAll()) {
			System.out.println(b);
		}
	}
}
//
세션 생성 성공
Board [id=1, title=BackEnd 너두 마슷허, writer=양씨, content=너도 할 수 있어, regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=2, title=누르지마시오, writer=따봉맨, content=아무내용없음, regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=3, title=대답잘하는 법, writer=송소연, content=채팅 잘치면됨 네(필쑤), regDate=23-04-19 13:38:05, viewCnt=0]

MySql과 연결하여 글 하나 불러오기

나머지 코드는 위와 동일
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssafy.board.model.dao.BoardDao">
	<resultMap type="Board" id="boardMap">
		<result column="id" property="id"/>
		<result column="writer" property="writer"/>
		<result column="title" property="title"/>
		<result column="content" property="content"/>
		<result column="view_cnt" property="viewCnt"/>
		<result column="reg_date" property="regDate"/>
	</resultMap>

<!-- 	상세글 조회  -->
	<select id="selectOne" parameterType="int" resultMap="boardMap">
    위에 전체글 조회처럼 resultType="Board"라고 써도 되고
    위에 <resultMap>을 지정해줘서 resultMap에 아이디를 써서
    view_cnt as viewCnt, date_format(reg_date, '%y-%m-%d %H:%i:%s') as regDate
	위의 이 부분을 as를 빼고 작성해줄 수 있다.
    parameterType부분에 위의 인터페이스에서의 파라미터 안에 int를 넣어줘야한다.
		SELECT id, content, writer, title, view_cnt, date_format(reg_date, '%y-%m-%d') as reg_date
		FROM board
		WHERE id = #{id};
        들어가는 반환값의 id인 값을->WHERE
	</select>
</mapper>    
==================================================================
Test.java
package com.ssafy.board.test;

import com.ssafy.board.config.MyAppSqlConfig;
import com.ssafy.board.model.dao.BoardDao;
import com.ssafy.board.model.dto.Board;

public class Test {
	public static void main(String[] args) {
		BoardDao dao = MyAppSqlConfig.getSession().getMapper(BoardDao.class);
		System.out.println(dao.selectOne(1));		
	}
}
//
세션 생성 성공
Board [id=1, title=BackEnd 너두 마슷허, writer=양씨, content=너도 할 수 있어, regDate=23-04-19, viewCnt=0]

글 작성

나머지 코드는 위와 동일
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssafy.board.model.dao.BoardDao">
	<resultMap type="Board" id="boardMap">
		<result column="id" property="id"/>
		<result column="writer" property="writer"/>
		<result column="title" property="title"/>
		<result column="content" property="content"/>
		<result column="view_cnt" property="viewCnt"/>
		<result column="reg_date" property="regDate"/>
	</resultMap>
	
<!-- 	게시글 등록  -->
	<insert id="insertBoard" parameterType="Board">
		INSERT INTO board (title, writer, content)
		VALUES (#{title}, #{writer}, #{content})
	</insert>
</mapper>
=====================================================================
Test.java
package com.ssafy.board.test;

import com.ssafy.board.config.MyAppSqlConfig;
import com.ssafy.board.model.dao.BoardDao;
import com.ssafy.board.model.dto.Board;

public class Test {
	public static void main(String[] args) {
		BoardDao dao = MyAppSqlConfig.getSession().getMapper(BoardDao.class);
		
		Board board = new Board("이거 되나요요요요 ??", "이종민", "select * ....");
		
		dao.insertBoard(board);
		for (Board b : dao.selectAll()) {
			System.out.println(b);
		}		
	}
}
//
세션 생성 성공
Board [id=1, title=BackEnd 너두 마슷허, writer=양씨, content=너도 할 수 있어, regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=2, title=누르지마시오, writer=따봉맨, content=아무내용없음, regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=3, title=대답잘하는 법, writer=송소연, content=채팅 잘치면됨 네(필쑤), regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=4, title=이거 되나요요요요 ??, writer=이종민, content=select * ...., regDate=23-04-19 14:20:47, viewCnt=0]

글 삭제

나머지 코드는 위와 동일
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssafy.board.model.dao.BoardDao">
	<resultMap type="Board" id="boardMap">
		<result column="id" property="id"/>
		<result column="writer" property="writer"/>
		<result column="title" property="title"/>
		<result column="content" property="content"/>
		<result column="view_cnt" property="viewCnt"/>
		<result column="reg_date" property="regDate"/>
	</resultMap>

<!-- 	게시글 삭제 -->
	<delete id="deleteBoard" parameterType="int">
		DELETE FROM board
		WHERE id = #{id}
	</delete>
</mapper>
====================================================================
Test.java
package com.ssafy.board.test;

import com.ssafy.board.config.MyAppSqlConfig;
import com.ssafy.board.model.dao.BoardDao;
import com.ssafy.board.model.dto.Board;

public class Test {
	public static void main(String[] args) {
		BoardDao dao = MyAppSqlConfig.getSession().getMapper(BoardDao.class);

		dao.deleteBoard(1);
        
		for (Board b : dao.selectAll()) {
			System.out.println(b);
		}
	}
}
//
세션 생성 성공
Board [id=2, title=누르지마시오, writer=따봉맨, content=아무내용없음, regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=3, title=대답잘하는 법, writer=송소연, content=채팅 잘치면됨 네(필쑤), regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=4, title=이거 되나요요요요 ??, writer=이종민, content=select * ...., regDate=23-04-19 14:20:47, viewCnt=0]

조회수 늘리기

나머지 코드는 위와 동일
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssafy.board.model.dao.BoardDao">
	<resultMap type="Board" id="boardMap">
		<result column="id" property="id"/>
		<result column="writer" property="writer"/>
		<result column="title" property="title"/>
		<result column="content" property="content"/>
		<result column="view_cnt" property="viewCnt"/>
		<result column="reg_date" property="regDate"/>
	</resultMap>

<!-- 	조회수 증가  -->
	<update id="updateViewCnt" parameterType="int">
		UPDATE board
		SET view_cnt = view_cnt+1
		WHERE id = #{id}
	</update>
</mapper>
==================================================================
Test.java
package com.ssafy.board.test;

import com.ssafy.board.config.MyAppSqlConfig;
import com.ssafy.board.model.dao.BoardDao;
import com.ssafy.board.model.dto.Board;

public class Test {
	public static void main(String[] args) {
		BoardDao dao = MyAppSqlConfig.getSession().getMapper(BoardDao.class);

		dao.updateViewCnt(4);
        
		for (Board b : dao.selectAll()) {
			System.out.println(b);
		}
	}
}
//
세션 생성 성공
Board [id=2, title=누르지마시오, writer=따봉맨, content=아무내용없음, regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=3, title=대답잘하는 법, writer=송소연, content=채팅 잘치면됨 네(필쑤), regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=4, title=이거 되나요요요요 ??, writer=이종민, content=select * ...., regDate=23-04-19 14:20:47, viewCnt=2]
실행할수록 조회수가 하나씩 늘어남

게시글 수정

나머지 코드는 위와 동일
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssafy.board.model.dao.BoardDao">
	<resultMap type="Board" id="boardMap">
		<result column="id" property="id"/>
		<result column="writer" property="writer"/>
		<result column="title" property="title"/>
		<result column="content" property="content"/>
		<result column="view_cnt" property="viewCnt"/>
		<result column="reg_date" property="regDate"/>
	</resultMap>

<!-- 	게시글 수정 -->
<!-- 	지금 게시글 날짜는 등록 날짜만 존재한다. 나중에 수정날짜도 같이 관리하게 된다면의 상황을보자ㅏ...  -->
	<update id="updateBoard" parameterType="Board">
 		UPDATE board
 		SET title = #{title}, content=#{content}, reg_date = now()
        reg_date를 now()하며 수정한 시간까지 초기화해줄 수 있다.
 		WHERE id=#{id}
 	</update>
</mapper>
===================================================================
Test.java
package com.ssafy.board.test;

import com.ssafy.board.config.MyAppSqlConfig;
import com.ssafy.board.model.dao.BoardDao;
import com.ssafy.board.model.dto.Board;

public class Test {
	public static void main(String[] args) {
		BoardDao dao = MyAppSqlConfig.getSession().getMapper(BoardDao.class);

		Board bb = dao.selectOne(3);
		bb.setTitle("대답잘하는법 공유해드림");
		bb.setContent("채팅 뿐만아니라 열정도 있어야함.");
		
		dao.updateBoard(bb);

		for (Board b : dao.selectAll()) {
			System.out.println(b);
		}
	}
}
//
세션 생성 성공
Board [id=2, title=누르지마시오, writer=따봉맨, content=아무내용없음, regDate=23-04-19 13:38:05, viewCnt=0]
Board [id=3, title=대답잘하는법 공유해드림, writer=송소연, content=채팅 뿐만아니라 열정도 있어야함., regDate=23-04-19 14:41:35, viewCnt=0]
Board [id=4, title=이거 되나요요요요 ??, writer=이종민, content=select * ...., regDate=23-04-19 14:20:47, viewCnt=2]