데이터를 DB에 저장하는 방법
- JDBC (java)
- Spring JDBC (ex. jdbcTemplate)
- Persistence Framework (Ex. Hibernate, Mybatis 등)
Persistence Framework
JDBC 프로그래밍의 복잡함이나 번거로움 없이 간단한 작업만으로 데이터베이스와 연동되는 시스템을
빠르게 개발할 수 있으며 안정적인 구동을 보장한다.
Persistence Framework는 SQL Mapper와 ORM으로 나눌 수 있다.
ex) JPA, Hibernate, Mybatis 등
ORM(Object Relational Mapping)이란?
객체와 관계형 데이터를 서로 매핑해주는 것!
객체 지향 프로그램은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다.
객체 모델과 관계형 모델 간에 불일치가 존재할 수 있는데 ORM을 통해 객체 간의 관계를 바탕으로
SQL을 자동으로 생성하여 불일치를 해결해준다.
Mybatis 프레임워크 장점
객체 지향적인 코드로 인해 더 직관적이고 비즈니스 로직에 더 집중할 수 있도록 도와준다.
자바코드로부터 SQL문을 분리(분리된 SQL문들은 .xml에서 관리)하여 응집도를 높이며
따라서 협업에 용이, 재사용 및 유지보수성 증가한다.
또한 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하기 때문에 DBMS에 대한 종속성이 줄어든다.
Mybatis 프레임워크 단점
코드가 간결해지는 대신 설정이 많아지며, DBMS의 고유 기능을 이용하기 어렵다.
Mybatis == Data Mapper
SQL 문의 수행 결과를 VO 자바 객체에 담아서 자바 코드로 가져올 수 있다.
※ Ibatis -> Mybatis : 동일한 프레임워크로써 명칭만 달라졌을 뿐 기술은 같음!
이클립스 Mybatis 설치 및 설정
1. Marketplace에서 ORM(Object Relational Mapping) 플러그인 설치
만약 마켓에 위와 같은 플러그인이 없다면, MyBatipse 1.2.4 설치
2. Spring Legacy Project 생성
기본적인 slp 설정을 마친 후, pom.xml에 Mybatis dependency 추가
<!-- Mybatis 프레임워크를 위한 설정 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.ibatis</groupId>
<artifactId>ibatis-core</artifactId>
<version>3.0</version>
</dependency>
3. 테이블에 대한 mapping.xml을 생성 (-> DAO 비즈니스 메서드 구현 파트)
위와 같이 패키지명 파일명 맞춰줄 것!
mapping.xml 파일에 다음과 같이 SQL 쿼리문 작성
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao">
<!-- id값은 유일해야하며 해당 메소드를 지정해줌
실행 시 해당 네임스페이스를 지정하고, id로 메소드를 호출한다.
-->
<!-- parameterType : input 파라미터 ex) prameterType="board" (생략가능) -->
<insert id="insertBoard">
INSERT INTO BOARD (WPK, TITLE, ID, CONTENT) VALUES (NVL((SELECT MAX(WPK) FROM BOARD),0)+1, #{title}, #{id}, #{content})
</insert>
<update id="updateBoard">
UPDATE BOARD SET TITLE = #{title}, CONTENT = #{content} WHERE WPK = #{wpk}
</update>
<delete id="deleteBoard">
DELETE BOARD WHERE WPK = #{wpk}
</delete>
<!-- select 엘리먼트(요소)는 속성으로 resultType(or resultMap)을 필요로 한다!
수행 결과(output)를 boardVO에 매핑하여 저장 -->
<select id="getBoardList" resultType="board">
SELECT * FROM BOARD ORDER BY WDATE DESC
</select>
<select id="getBoard" resultType="board">
SELECT * FROM BOARD WHERE WPK = #{wpk} ORDER BY WDATE DESC
</select>
</mapper>
resultMap 사용 시 다음과 같은 방법으로 적용
<!-- SQL문 실행결과와 자바객체(VO)를 연결해주는 매퍼(Mapper) -->
<resultMap type="board" id="boardResult">
<result property="title" column="TITLE" />
</resultMap>
<select id="getBoardList" resultMap="boardResult">
SELECT * FROM BOARD ORDER BY WDATE DESC
</select>
VO 이름 설정, JDBC 연결 설정, DBMS 관련 설정 필요
configuration.xml 파일이 필요한데 MyBatipse 1.2.4만 설치한 경우 해당 파일이 존재하지 않는다.
따라서 Generator도 추가로 설치!
설치 후 configurator file 생성
파일명은 sql-map-config.xml로 설정
위의 기본 코드를 아래와 같이 수정해줘야함!
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
sql-map-config.xml 파일에 설정해야 할 항목들
1. JDBC와의 Connection을 확보하기 위한 설정 -> 결합도를 낮추기 위해 properties에 JDBC 정보를 담아둔다.
<properties resource="db.properties" />
1-1. db.properties 파일에 JDBC 연결 정보 작성 (일반 file로 생성)
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.username=sngynhy
jdbc.password=****
2. VO 이름(별칭) 설정 - 여러 개 사용 가능하며 VO당 설정해준다.
<typeAliases>
<typeAlias alias="board" type="model.board.BoardVO"/>
</typeAliases>
3. DataSource 설정
<!-- DataSource 설정 (Connection 관리 - 연결 및 해제)-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
4. mappings 패키지 내부 mapping.xml 설정 파일에 작성된 메서드와의 연결 설정
<!-- resource = "패키지명/파일명.xml" -->
<mappers>
<mapper resource="mappings/board-mapping.xml" />
</mappers>
sql-map-config.xml 전체 코드
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- VO 이름 설정, 연결 설정, DBMS 관련 설정 필요 -->
<!-- JDBC와의 Connection을 확보하기 위한 설정 -->
<properties resource="db.properties" />
<!-- VO 별칭 설정 -->
<typeAliases>
<typeAlias alias="board" type="model.board.BoardVO"/>
</typeAliases>
<!-- DataSource 설정 (Connection 관리 - 연결 및 해제)-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- mappings 패키지 내부의 케서드 (==설정파일)와의 연결 설정
resource = "패키지명/파일명.xml" -->
<mappers>
<mapper resource="mappings/board-mapping.xml" />
</mappers>
</configuration>
각 설정 파일들의 생성 위치
[DAO]
import java.util.List;
import org.apache.ibatis.session.SqlSession;
public class BoardDAO {
private SqlSession mybatis;
public BoardDAO() {
mybatis = sqlSessionFactoryBean.getSqlSessionInstance();
}
public void insertBoard(BoardVO vo) {
mybatis.insert("dao.insertBoard", vo); // board-mappins.xml에서 설정한 namespace로 메소드를 호출할 수 있음
mybatis.commit();
}
public void updateBoard(BoardVO vo) {
mybatis.update("dao.updateBoard", vo);
mybatis.commit();
}
public void deleteBoard(BoardVO vo) {
mybatis.update("dao.deleteBoard", vo);
mybatis.commit();
}
public List<BoardVO> getBoardList() {
return mybatis.selectList("dao.getBoardList");
}
public BoardVO getBoard(BoardVO vo) {
return (BoardVO) mybatis.selectOne("dao.getBoard", vo);
}
}
[sqlSessionFactoryBean]
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 sqlSessionFactoryBean {
private static SqlSessionFactory sessionFactory = null; // DAO를 수행해줄 sql을 제공해주는 객체 세션 객체
static { // sessionFactory 생성
try {
if(sessionFactory == null) { // 싱글톤 패턴을 위한 조건 설정
Reader reader = Resources.getResourceAsReader("sql-map-config.xml"); // sql-map-config.xml의 설정을 읽어들임
sessionFactory = new SqlSessionFactoryBuilder().build(reader); // reader 내용을
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSessionInstance() {
return sessionFactory.openSession(); // sessionFactory 생성!
}
}
[main]
import java.util.List;
public class Client {
public static void main(String[] args) {
BoardDAO dao = new BoardDAO();
BoardVO vo = new BoardVO();
vo.setTitle("제목");
vo.setContent("내용");
vo.setId("작성자");
dao.insertBoard(vo);
List<BoardVO> datas = dao.getBoardList();
for(BoardVO v : datas) {
System.out.println(v );
}
}
}
[실행 결과]
스프링에 Mybatis 적용하기 위한 설정
1. pox.xml 설정 파일에 dependency 추가 - Mybatis와 Spring 연동을 위한 설정
<!-- Mybatis와 Spring 연동을 위한 설정 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.4</version>
</dependency>
2. applicationContext.xml 설정 파일 - sqlSessionFactoryBean 등록
<!-- sqlSessionFactoryBean 객체 등록 -->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sql-map-config.xml" />
</bean>
3. mapping.xml 설정 - sql문 작성, 쿼리문을 수행할 객체명 설정
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao">
<insert id="insertBoard">
<![CDATA[
INSERT INTO BOARD (WPK, TITLE, ID, CONTENT) VALUES (NVL((SELECT MAX(WPK) FROM BOARD),0)+1, #{title}, #{id}, #{content})
]]>
</insert>
<update id="updateBoard">
<![CDATA[
UPDATE BOARD SET TITLE = #{title}, CONTENT = #{content} WHERE WPK = #{wpk}
]]>
</update>
<delete id="deleteBoard">
<![CDATA[
DELETE BOARD WHERE WPK = #{wpk}
]]>
</delete>
<select id="getBoardList" resultType="board">
<![CDATA[
SELECT * FROM BOARD ORDER BY WDATE DESC
]]>
</select>
<select id="getBoard" resultType="board">
<![CDATA[
SELECT * FROM BOARD WHERE WPK = #{wpk} ORDER BY WDATE DESC
]]>
</select>
</mapper>
※ CDATA Section
.xml 파일은 xml 파서가 태그(요소) 단위로 처리하기 때문에 비교연산자나 부등호를 사용할 시 CDATA Section 처리.
CDATA로 처리된 구문은 온전히 캐릭터 영역으로 판단하여 xml 파서가 해석하지 않음.
4. sql-map-config.xml 설정
<!-- VO 별칭 설정 -->
<typeAliases>
<typeAlias alias="board" type="model.board.BoardVO"/>
</typeAliases>
<!-- mappings 패키지 내부의 메서드 (==mapping.xml)와의 연결 설정 -->
<mappers>
<mapper resource="mappings/board-mapping.xml" />
</mappers>
※ DataSource나 JDBC Connectiond은 applicationContext.xml에서 등록했기 때문에 위의 파일에서는
VO 별칭 설정과 mapping.xml와의 연결 설정만 해주면 된다.
구현
방법1) SqlSessionDaoSupport 클래스를 상속받아 구현
import java.util.List;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
public class MybatisBoardDAO1 extends SqlSessionDaoSupport { // jdbcTemplate과 유사
@Autowired // applicationContext.xml에 등록한 sessionFactory 객체 주입
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
public void insertBoard(BoardVO vo) {
getSqlSession().insert("dao.inserBoard", vo);
}
public void updateBoard(BoardVO vo) {
getSqlSession().update("dao.updateBoard", vo);
}
public void deleteBoard(BoardVO vo) {
getSqlSession().delete("dao.deleteBoard", vo);
}
public BoardVO getBoard(BoardVO vo) {
return (BoardVO) getSqlSession().selectOne("dao.getBoard", vo);
}
public List<BoardVO> getBoardList(BoardVO vo) {
return getSqlSession().selectList("dao.getBoardList", vo);
}
}
방법2) SqlSessionTemplate 사용
2-1. applicationContext.xml 설정 파일에 SqlSessionTemplate 객체 등록
<<!-- SqlSessionTemplate 객체 등록 -->
<bean class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sessionFactory"></constructor-arg>
</bean>
2-2. 어노테이션 사용
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class MybatisBoardDAO2 {
@Autowired
private SqlSessionTemplate mybatis;
public void insertBoard(BoardVO vo) {
mybatis.insert("dao.inserBoard", vo);
}
public void updateBoard(BoardVO vo) {
mybatis.update("dao.updateBoard", vo);
}
public void deleteBoard(BoardVO vo) {
mybatis.delete("dao.deleteBoard", vo);
}
public BoardVO getBoard(BoardVO vo) {
return (BoardVO) mybatis.selectOne("dao.getBoard", vo);
}
public List<BoardVO> getBoardList(BoardVO vo) {
return mybatis.selectList("dao.getBoardList", vo);
}
}
'개발 공부 > Spring' 카테고리의 다른 글
[Spring] JPA (0) | 2021.11.03 |
---|---|
[Mybatis] Dynamic SQL (0) | 2021.11.02 |
[Spring] 다국어 처리 (0) | 2021.10.28 |
[Spring] 트랜잭션 관리자 설정 (0) | 2021.10.13 |
[Spring] 스프링의 JDBC - jdbcTemplate (0) | 2021.10.11 |