💡 기존 바닐라 형태 JDBC는 연동 과정도 복잡하고, 반복적인 코드가 나오면서 SQL 문장이 자바 코드와 섞여 있어서 유지보수가 힘들다. 따라서 이런 점을 개선하여 편의성과 유지보수성을 높이기 위하 목적으로 사용된다.
깔끔한 소스 코드
를 유지할 수 있다.Map에 Mapping
된다.VO에도 저장이 가능
하다.XML 파일
로 관리한다.
- Location : http://mybatis.org/dtd/mybatis-3-config.dtd
- Key Type : Public ID (Default)
- Key : -//mybatis.org/DTD Config 3.0//EN
- Location : http://mybatis.org/dtd/mybatis-3-mapper.dtd
- Key Type : Public ID (Default)
- Key : -//mybatis.org/DTD Mapper 3.0//EN
<?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>
<!-- driver properties 파일-->
<properties resource="./driver.properties" />
<!-- MyBatis setting에 대한 내용 -->
<settings>
<setting name="jdbcTypeForNull" value="NULL"/>
<!-- 만약 MyBatis의 SQL Query(select)를 이용해서 처리했는데
데이터베이스에서 가져온 내용이 없다면 Java 객체 NULL로 리턴한다. -->
</settings>
<!-- Alias를 설정할 수 있다. 여기서 설정하는 Alias(별칭)은 오직 XML에서만 사용된다.
단순히 타이핑을 줄이기 위한 용도로 사용된다. -->
<typeAliases>
<typeAlias alias="BookVO" type="example.vo.BookVO" />
</typeAliases>
<!-- Database 연결에 대한 설정
일반적으로 개발용, 운영용처럼 여러 개의 환경을 설정해놓고
상황에 맞게 이용하는 방식을 사용한다. -->
<environments default="development">
<environment id="development">
<!-- transactionManager는 type이 2개가 있다.
JDBC라고 쓰면 수동으로 transaction을 관리한다는 의미
MANAGED라고 쓰면 Container가 TR을 관리한다는 의미 -->
<transactionManager type="JDBC">
</transactionManager>
<!-- dataSource 설정은 Connection Pool 설정하는 것이다.
#{}이랑 ${}이랑 의미가 조금 다르다. -->
<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>
<!-- 사용할 Mapper에 대한 설정이 나온다. -->
<mappers>
<mapper resource="./sqlmap/Book.xml" />
</mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="example.mybook">
<select id="selectByISBNHashMap" parameterType="String" resultType="HashMap">
<![CDATA[
SELECT bisbn, btitle, bprice, bauthor
FROM book
WHERE bisbn = #{bisbn}
]]>
</select>
<select id="selectByAllHashMap" parameterType="String" resultType="HashMap">
<![CDATA[
SELECT bisbn, btitle, bprice, bauthor
FROM book
]]>
</select>
<select id="selectByISBNBookVO" parameterType="String" resultType="BookVO">
<![CDATA[
SELECT bisbn, btitle, bprice, bauthor
FROM book
WHERE bisbn = #{bisbn}
]]>
</select>
<resultMap id="result_1" type="BookVO">
<result property="bisbn" column="my_isbn" jdbcType="VARCHAR" javaType="String" />
<result property="btitle" column="my_title" />
<result property="bprice" column="my_price" />
<result property="bauthor" column="my_author" />
</resultMap>
<select id="selectByISBNResultMap" parameterType="String" resultMap="result_1">
<![CDATA[
SELECT bisbn AS my_isbn,
btitle AS my_title,
bprice AS my_price,
bauthor AS my_author
FROM book
WHERE bisbn = #{bisbn}
]]>
</select>
<update id="titleUpdate" parameterType="BookVO">
<![CDATA[
UPDATE book
SET btitle = #{btitle}
WHERE bisbn = #{bisbn}
]]>
</update>
</mapper>
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/library?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
username=root
password=****
package example.dao;
import example.vo.BookVO;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.HashMap;
import java.util.List;
public class BookDAO {
// 여기서 SqlSessionFactory를 직접 얻어내지 않는다.
// 생성자를 통해 주입받아서 사용한다.
private SqlSessionFactory sqlSessionFactory;
public BookDAO() {
}
// 생성자 주입 Constructor Injection
public BookDAO(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
// 1. ISBN 번호를 입력으로 받아서 책 1권의 데이터를 HashMap으로 만들어서 리턴하는 method를 작성해보자.
public HashMap<String, Object> selectByISBNHashMap(String bisbn) {
HashMap<String, Object> result = null;
SqlSession session = sqlSessionFactory.openSession();
try {
result = session.selectOne("example.mybook.selectByISBNHashMap", bisbn);
} catch (Exception e) {
System.out.println(e);
} finally {
session.close();
}
return result;
}
// 2. 모든 책의 데이터를 HashMap의 List로 만들어서 리턴하는 method를 작성해보자.
public List<HashMap<String, Object>> selectByAllHashMap() {
List<HashMap<String, Object>> result = null;
SqlSession session = sqlSessionFactory.openSession();
try {
result = session.selectList("example.mybook.selectByAllHashMap");
} catch (Exception e) {
System.out.println(e);
} finally {
session.close();
}
return result;
}
// 3. ISBN 번호를 입력으로 받아서 책 1권의 데이터를 BookVO로 만들어서 리턴하는 method를 작성해보자.
public BookVO selectByISBNBookVO(String bisbn) {
BookVO result = null;
SqlSession session = sqlSessionFactory.openSession();
try {
result = session.selectOne("example.mybook.selectByISBNBookVO", bisbn);
} catch (Exception e) {
System.out.println(e);
} finally {
session.close();
}
return result;
}
// 4. ISBN 번호를 이용해서 책 1권의 정보를 BookVO로 변환해서 가져오기
// 그러나 table의 column명이 VO의 field명과 다른 경우 하는 방법
public BookVO selectByISBNResultMap(String bisbn) {
BookVO result = null;
SqlSession session = sqlSessionFactory.openSession();
try {
result = session.selectOne("example.mybook.selectByISBNBookVO", bisbn);
} catch (Exception e) {
System.out.println(e);
} finally {
session.close();
}
return result;
}
// 5. ISBN 번호를 이용해서 책 1권의 정보를 변경하고 싶다.
// 책 제목을 바꿀 때
public int titleUpdate(BookVO bookVO) {
int result = 0;
SqlSession session = sqlSessionFactory.openSession();
try {
result = session.update("example.mybook.titleUpdate", bookVO);
} catch (Exception e) {
System.out.println(e);
} finally {
session.commit(); // update 계열은 반드시 처리해야 한다. 하지 않으면 데이터베이스에 반영이 안된다.
session.close();
}
return result;
}
}
package example.mybatis;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.Reader;
public class MyBatisConnectionFactory {
// 실제 프로그램에서 (DAO)에서 사용하는 데이터베이스 연결 객체는
// 기존에는(JDBC)일 때는 Connection 객체를 이용했다.
// MyBatis에서는 SqlSession이라는 객체를 이용한다.
private static SqlSessionFactory sqlSessionFactory;
// 이 Factory 객체는 해당 클래스로부터 객체가 1개만 만들어져서 사용되도록 처리할 것이다.
// => Singleton으로 동작하게끔 만든다.
static {
try {
String resource = "./SqlMapConfig.xml";
Reader reader = Resources.getResourceAsReader(resource);
if (sqlSessionFactory == null) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
} catch (Exception e) {
System.out.println(e);
}
}
public static SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
}
}
package example.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookVO {
private String bisbn;
private String btitle;
private int bprice;
private String bauthor;
}
package example;
import example.dao.BookDAO;
import example.mybatis.MyBatisConnectionFactory;
import example.vo.BookVO;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.HashMap;
import java.util.List;
public class Main {
public static void main(String[] args) {
// 데이터베이스 처리
// DAO가 있어야 데이터베이스 처리를 할 수 있다.
// DAO를 만들려면 SqlSessionFactory를 먼저 확보해야 이것을 주입해서 DAO를 만들 수 있다.
SqlSessionFactory factory = MyBatisConnectionFactory.getSqlSessionFactory();
BookDAO dao = new BookDAO(factory);
// 1.
// HashMap<String, Object> result = dao.selectByISBNHashMap("89-7914-274-9");
//
// for (String key : result.keySet()) {
// System.out.println(key + " : " + result.get(key));
// }
// 2.
// List<HashMap<String, Object>> result = dao.selectByAllHashMap();
// for(HashMap<String, Object> map : result) {
// for (String key: map.keySet()) {
// System.out.println(key + " : " + map.get(key));
// }
// System.out.println();
// }
// 3. ISBN 번호로 책 1권의 정보 BookVO로 변환
// BookVO result = dao.selectByISBNBookVO("89-7914-274-9");
// System.out.println(result);
// 4. ISBN 번호를 이용해서 책 1권의 정보를 BookVO로 변환해서 가져오기
// 그러나 table의 column명이 VO의 field명과 다른 경우 하는 방법
// BookVO result = dao.selectByISBNResultMap("89-7914-274-9");
// System.out.println(result);
// 5. ISBN 번호를 이용해서 책 1권의 정보를 변경하고 싶다.
// 책 제목을 바꿀 때
BookVO bookVO = new BookVO("89-7914-274-9", "나는 고수 프로그래머다.", 0, null);
int result = dao.titleUpdate(bookVO);
System.out.println("영향을 받은 행의 개수: " + result);
}
}