💡 기존 바닐라 형태 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);
}
}