MyBatis 프레임워크
1. 개요
- JDBC 사용을 편리하고 효율적으로 기능이 추가된 형태의 SQL Mapping Framework 프레임워크.
- ibatis ( OLD 버전; mybatis 이전 버전 )
2. 홈페이지 가서 필요한 jar 다운로드 하자.
http://mybatis.org
1) mybatis-3.5.14
2) assets -> mybatis-3.5.14.zip 다운
3) 압축풀기
mybatis-3.5.14.jar ( build path 대상임 )
mybatis-3.5.14.pdf ( 매뉴얼, https://mybatis.org/mtbatis-3/ )
3. 이클립스에서 build path
1) 프로젝트 생성
2) 2개의 jar 파일 build path
- mysql-connector-j-8.jar (mysql 드라이버)
- mybatis-3.5.14.jar
- 자바프로젝트 선택 > 오른쪽 클릭 > build path > Configure build path > Libraries >
ClassPath > ADD External jar... > mysql-connector-j-8.3.0.jar 선택( .jar 파일로 선택해야함. )
4. MyBatis 사용방법
1) JDBC 에서 사용햇던 4가지 정보를 외부파일에 저장.
=> jdbc.properties
=> src 폴더에 저장. ( 패키지 설정 가능 )
* properties 파일
key=value
key=value
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.userid=root
jdbc.passwd=1234
2) 최소 2개의 xml 파일이 필요
=> *.xml
=> src 폴더에 저장. ( 패키지 설정 가능 )
가. 설정파일
- 용도 : mybtis 사용시 환경설정 정보들 관리 ( DB 연동정보, DTO별칭, mapper 등록 )
- Configuration.xml
나. mapper 파일
- 용도: JDBC 에서 사용했던 SQL 문을 저장하는 파일.
- 테이블당 하나씩 작성. ( 테이블명Mapper.xml )
- DeptMapper.xml
EmpMapper.xml
https://mybatis.org/mybatis-3/getting-started.html 에서 Configuration 과 Mapper xml 복사하였음.
* Configuration.xml 파일을 읽는 자바 코드가 필요.
==> com.config.MySqlSessionFactory.java 만들고 하단코드를 복사해서 사용.
``
String resource = "com/config/Configuration.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
``
* JDBC vs MyBatis
가. JDBC 에서 필요한 API
- Connection
- PrepareStatement
- ResultSet
나. MyBatis 에서 필요한 API
- SqlSesstionFactory
- SqlSession ( * )
==> SqlSession session = MySqlSessionFactory.getSession( );
* SqlSession 의 메서드
==> DeptMapper.xml 에 있는 태그를 호출하는 메서드
가. select 작업
# 단일 레코드 반환
DeptDTO dto = session.selectOne( " namespace명.mapper 의 id값 " );
DeptDTO dto = session.selectOne( " namespace명.mapper 의 id값 ", Onject obj ); // obj 는 WHERE 절에 사용
# 다중 레코드 반환
List<DeptDTO> list = session.selectList( " namespace명.mapper 의 id값 " );
List<DeptDTO> list = session.selectList( " namespace명.mapper 의 id값 ", Object obj ); // obj 는 WHERE 절에 사용
나. insert 작업
int n = session.insert( " namespace명.mapper 의 id값 " );
int n = session.insert( " namespace명.mapper 의 id값 ", Object obj ); // obj 는 저장할 데이터
다. update 작업
int n = session.update( " namespace명.mapper 의 id값 " );
int n = session.update( " namespace명.mapper 의 id값 ", Object obj ); // obj 는 수정할 데이터
라. delete 작업
int n = session.delete( " namespace명.mapper 의 id값 " );
int n = session.delete( " namespace명.mapper 의 id값 ", Object obj ); // obj 는 삭제할 데이터
3) 하나의 레코드를 저장하는 DTO 작성 ( * )
==> select 된 결과인 레코드를 DTO 에 저장한다.
단, 연결고리가 존재한다.
테이블의 컬럼명(컬럼헤더값)과 DTO 의 변수명이 일치해야 된다.
ex)
CREATE TABLE dept
( deptno INT PRIMARY KEY,
dname VARCHAR(20),
loc VARCHAR(20) );
SELECT deptno AS no, dname, loc FROM dept; -- int deptno 에 저장안됨.
public class DeptDTO {
int deptno;
String dname;
String loc;
}
* parameterType="전달할 파라미터의 타입" 종류
https://mybatis.org/mybatis-3/configuration.html#typealiases
* 자동으로 select 한 결과가 DTO 저장이 되고 반대로 파라미터로 전달한
DTO 의 변수값이 #{ 변수값 } ( getXXX 이용 ) 로 치환이 됨.
- 가능한이유? 테이블의 컬럼명과 DTO 의 변수명이 일치하기 때문이다.
정확한 문법은 컬럼명과 DTO 의 getXXX( ) 와 setXXX( ) 가 되어야 한다.
* id 값이 일치하지 않는 경우의 에러
Mapped Statements collection does not contain value for findByDnameOrLoc3 ....
이런오류가 난다면 id 값이 잘못적힌것이니 최대한 id 는 복사붙여넣기 할것.
4) com.dto.DeptDTO 의 별칭 지정하기
==> com.dto.DeptDTO 를 DeptDTO(별칭) 로 지정
==> Configuration.xml 에서 별칭 지정하고 Mapper 에서 별칭을 사용한다.
문법:
<typeAliases>
<typeAlias alias="DeptDTO" type="com.dto.DeptDTO"/>
</typeAliases>
##########################################################
5. MyBatis 동적sql( Dynamic SQL ) 처리 ( emp 테이블로 실습 )
1) 다중 insert 처리
mysql sql 문:
INSERT INTO emp ( empno, ename, sal )
VALUES ( 10, 'a', 100 ), ( 20, 'a', 100 ), ( ), ....; -- 동적으로 처리
mybatis sql 문:
<insert id="multiInsert" parameterType="arraylist">
INSERT INTO emp ( empno, ename, sal )
VALUES
<foreach item="dto" collection=" list ", separator=" , ">
( #{ dto.empno }, #{ dto.ename }, #{ dto.sal } )
</foreach> <!-- list 갯수만큼 반복해서 ( ) 를 만듬 -->
</insert>
``
<공통> ----------------------------------------------------------------------------------------------------------------------------------------------------
# com.config 를 생성후 jdbc.properties 를 text 형식으로 만들어서 하단의 텍스트 추가
# 단, 한글로 쓰면 깨지게 되니 마우스 우클릭후 properties 에서 UTF-8 설정
# 주석문
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.userid=root
jdbc.passwd=1234
properties 설정하는 이미지 ↓
package com.config;
import java.io.IOException;
import java.io.InputStream;
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 MySqlSessionFactory {
static SqlSessionFactory sqlSessionFactory;
static {
String resource = "com/config/Configuration.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}// end static 블럭
// SqlSessionFactory 로부터 SqlSession 얻는 메서드
public static SqlSession getSession() {
// MyBatis는 명시적으로 commit 지정해야 된다.
SqlSession session = sqlSessionFactory.openSession(); // openSession(false) 동일
return session;
}
}
<?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>
<!-- jdbc.properties 등록 -->
<properties resource="com/config/jdbc.properties"></properties>
<!-- DTO 별칭 -->
<typeAliases>
<typeAlias type="com.dto.DeptDTO" alias="DeptDTO"/>
<typeAlias type="com.dto.EmpDTO" alias="EmpDTO"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<!-- jdbc.properties 등록된 값을 참조: ${key} -->
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.userid}" />
<property name="password" value="${jdbc.passwd}" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- DeptMapper.xml 등록 -->
<mapper resource="com/config/DeptMapper.xml" />
<mapper resource="com/config/DeptMapper2.xml" />
<mapper resource="com/config/EmpMapper.xml"/>
</mappers>
</configuration>
<DeptDTO>
package com.dto;
// 역할: dept 테이블의 컬럼(레코드)을 저장하는 역할.
// 규칙: select 할 때 반환되는 컬럼의 헤더값으로 변수를 지정해야 된다.
public class DeptDTO {
int deptno;
String dname;
String loc;
public DeptDTO() {
// TODO Auto-generated constructor stub
}
public DeptDTO(int deptno, String dname, String loc) {
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "DeptDTO [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
}
}
<EmpDTO>
package com.dto;
public class EmpDTO {
int empno;
String ename;
String job;
int mgr;
String hiredate; // 날자는 연산이 필요없으면 그냥 String 으로 처리
int sal;
int comm;
int deptno;
public EmpDTO() {
// TODO Auto-generated constructor stub
}
public EmpDTO(int empno, String ename, String job, int mgr, String hiredate, int sal, int comm, int deptno) {
this.empno = empno;
this.ename = ename;
this.job = job;
this.mgr = mgr;
this.hiredate = hiredate;
this.sal = sal;
this.comm = comm;
this.deptno = deptno;
}
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public String getHiredate() {
return hiredate;
}
public void setHiredate(String hiredate) {
this.hiredate = hiredate;
}
public int getSal() {
return sal;
}
public void setSal(int sal) {
this.sal = sal;
}
public int getComm() {
return comm;
}
public void setComm(int comm) {
this.comm = comm;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
@Override
public String toString() {
return "EmpDTO [empno=" + empno + ", ename=" + ename + ", job=" + job + ", mgr=" + mgr + ", hiredate="
+ hiredate + ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + "]";
}
}
---------------------------------------------------------------------------------------------------------------------------------------------------------
<기본사용>
import java.util.HashMap;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.config.MySqlSessionFactory;
import com.dto.DeptDTO;
public class MyBatisDeptMain {
public static void main(String[] args) {
//1. SqlSession 얻기
SqlSession session =
MySqlSessionFactory.getSession();
//2. SqlSession의 메서드를 이용해서 DeptMapper.xml과 연동
List<DeptDTO> list = session.selectList("findAll");
System.out.println("################################");
DeptDTO xxx = session.selectOne("findByDeptno", 10);
System.out.println("################################");
DeptDTO yyy = new DeptDTO();
yyy.setDname("인사과");
yyy.setLoc("BOSTON");
List<DeptDTO> list2 = session.selectList("findByDnameOrLoc", yyy);
System.out.println("################################");
HashMap<String, String> map = new HashMap<>();
map.put("x", "인사과");
map.put("y", "BOSTON");
List<DeptDTO> list3 = session.selectList("findByDnameOrLoc2", map);
//3. 출력
System.out.println(list3);
//4. close작업
session.close();
}
}
<?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.config.DeptMapper">
<!-- 전체 조회 -->
<select id="findAll" resultType="DeptDTO">
SELECT deptno, dname, loc
FROM dept
ORDER BY deptno DESC
</select>
<!-- 조건 조회1 -->
<!-- mapper 에서는 #{} / resultType: 결과값의 타입 / parameterType: 전달되는값의 타입(#{} 이 있으면 꼭 사용해야함.) -->
<select id="findByDeptno" resultType="DeptDTO" parameterType="int">
SELECT deptno, dname, loc
FROM dept
WHERE deptno = #{deptno}
</select>
<!-- 조건 조회2 -->
<select id="findByDnameOrLoc" resultType="DeptDTO" parameterType="DeptDTO">
SELECT deptno, dname, loc
FROM dept
WHERE dname = #{dname} OR loc = #{loc}
</select>
<!-- 조건 조회3 -->
<select id="findByDnameOrLoc2" resultType="DeptDTO" parameterType="hashmap">
SELECT deptno, dname, loc
FROM dept
WHERE dname = #{x} OR loc = #{y}
</select>
</mapper>
<응용>
id 를 적어주면 되지만 명확하게는 위치까지 같이 적어주는게 좋다.
import java.util.HashMap;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.config.MySqlSessionFactory;
import com.dto.DeptDTO;
// default package
public class MyBatisDeptMain1_select기초 {
public static void main(String[] args) {
// 1. SqlSession 얻기
SqlSession session =
MySqlSessionFactory.getSession();
// 2. SqlSession 의 메서드를 이용해서 DeptMapper.xml 과 연동
List<DeptDTO> list = session.selectList("com.config.DeptMapper.findAll"); // -> DeptMapper 의 select id="findAll" 연동
// --------------------------------------------------
DeptDTO xxx = session.selectOne("com.config.DeptMapper.findByDeptno", 10);
// --------------------------------------------------
DeptDTO yyy = new DeptDTO();
yyy.setDname("인사과");
yyy.setLoc("BOSTON");
List<DeptDTO> list2 = session.selectList("com.config.DeptMapper.findByDnameOrLoc",yyy);
// --------------------------------------------------
HashMap<String, String> map = new HashMap<>();
map.put("x", "인사과");
map.put("y", "BOSTON");
List<DeptDTO> list3 = session.selectList("com.config.DeptMapper.findByDnameOrLoc2",map);
// ---------------------------------------------------
// 3. 출력
System.out.println("--------------------------------");
System.out.println(list);
System.out.println("--------------------------------");
System.out.println(xxx);
System.out.println("--------------------------------");
System.out.println(list2);
System.out.println("--------------------------------");
System.out.println(list3);
// 4. close 작업
session.close();
}// end main
}// end class
<?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.config.DeptMapper">
<!-- 전체 조회 -->
<select id="findAll" resultType="DeptDTO">
SELECT deptno, dname, loc
FROM dept
ORDER BY deptno DESC
</select>
<!-- 조건 조회1 -->
<!-- mapper 에서는 #{} / resultType: 결과값의 타입 / parameterType: 전달되는값의 타입(#{} 이 있으면 꼭 사용해야함.) -->
<select id="findByDeptno" resultType="DeptDTO" parameterType="int">
SELECT deptno, dname, loc
FROM dept
WHERE deptno = #{deptno}
</select>
<!-- 조건 조회2 -->
<select id="findByDnameOrLoc" resultType="DeptDTO" parameterType="DeptDTO">
SELECT deptno, dname, loc
FROM dept
WHERE dname = #{dname} OR loc = #{loc}
</select>
<!-- 조건 조회3 -->
<select id="findByDnameOrLoc2" resultType="DeptDTO" parameterType="hashmap">
SELECT deptno, dname, loc
FROM dept
WHERE dname = #{x} OR loc = #{y}
</select>
</mapper>
----------------------------------------------------------------------------------------------------------------------------------------------------------
<DML>
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.config.MySqlSessionFactory;
import com.dto.DeptDTO;
// default package
public class MyBatisDeptMain2_DML {
public static void main(String[] args) {
// 1. SqlSession 얻기
SqlSession session = MySqlSessionFactory.getSession();
// List<DeptDTO> listDeptMapper = session.selectList("com.config.DeptMapper.findAll");
List<DeptDTO> list = session.selectList("com.config.DeptMapper2.findAll");
// System.out.println(listDeptMapper);
System.out.println(list);
// 데이터 저장 1 -------------------------------------------------
// DeptDTO dto = new DeptDTO(1, "개발", "부산");
// int n = session.insert("com.config.DeptMapper2.save", dto);
// session.commit();
// System.out.println(n + " 개가 생성됨.");
// 데이터 수정 -------------------------------------------------
DeptDTO dto2 = new DeptDTO(1, "IT개발", "부산시");
int n2 = session.update("com.config.DeptMapper2.update", dto2);
session.commit();
System.out.println(n2 + " 개가 업데이트됨.");
// 데이터 삭제 -------------------------------------------------
int deptno = 1;
int n3 = session.delete("com.config.DeptMapper2.remove",deptno);
session.commit();
System.out.println(n3 + " 개가 삭제됨.");
// 4. close 작업 -------------------------------------------------
session.close();
}// end main
}// end class
<?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.config.DeptMapper2">
<!-- 전체 조회 -->
<select id="findAll" resultType="DeptDTO">
SELECT deptno, dname, loc
FROM dept
ORDER BY deptno ASC
</select>
<!-- 저장 -->
<select id="save" parameterType="DeptDTO">
INSERT INTO dept ( deptno, dname, loc )
VALUES ( #{deptno}, #{dname}, #{loc} )
</select>
<!--
<select id="save2" parameterType="DeptDTO">
INSERT INTO dept ( deptno, dname )
VALUES ( #{}, #{dname} )
</select>
만약 값이 없다면 전체적으로 오류가 발생함으로 잘 확인할것.
-->
<!-- 수정 -->
<update id="update" parameterType="DeptDTO">
UPDATE dept
SET dname = #{dname}, loc = #{loc}
WHERE deptno = #{deptno}
</update>
<!-- 삭제 -->
<delete id="remove" parameterType="int">
DELETE FROM dept
WHERE deptno = #{deptno}
</delete>
<delete id="removeByDname" parameterType="String">
DELETE FROM dept
WHERE dname = #{dname}
</delete>
</mapper>
--------------------------------------------------------------------------------------------------------------------------------------------------------------
<emp 테이블 이용해서 mybatis 동적처리>
import java.util.Arrays;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.config.MySqlSessionFactory;
import com.dto.EmpDTO;
public class MyBatisEmpMain {
public static void main(String[] args) {
// 한꺼번에 저장
EmpDTO dto1 = new EmpDTO(1, "aaa1", "SALESMAN", 7369, null, 700, 0, 30);
EmpDTO dto2 = new EmpDTO(2, "aaa2", "SALESMAN", 7369, null, 700, 0, 30);
EmpDTO dto3 = new EmpDTO(3, "aaa3", "SALESMAN", 7369, null, 700, 0, 30);
List<EmpDTO> list = Arrays.asList(dto1, dto2, dto3);
SqlSession session = MySqlSessionFactory.getSession();
//
int n = session.insert("com.config.EmpMapper.multiInsert", list);
session.commit();
System.out.println(n + " 개가 저장됨.");
//
session.close();
}
}
<?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.config.EmpMapper">
<!--
INSERT INTO emp ( empno, ename, sal )
VALUES ( 10, 'a', 100 ), ( 20, 'a', 100 ), ( ), ....;
-->
<insert id="multiInsert" parameterType="arraylist">
INSERT INTO emp ( empno, ename, job, mgr, hiredate, sal, comm, deptno )
VALUES
<foreach item="dto" collection="list" separator=",">
( #{dto.empno}, #{dto.ename}, #{dto.job} , #{dto.mgr} ,now(), #{dto.sal}, #{dto.comm}, #{dto.deptno} )
</foreach>
</insert>
</mapper>
'[study]이론정리 > JDBC' 카테고리의 다른 글
MyBatis(4) 아키텍쳐 (0) | 2024.04.05 |
---|---|
MyBatis(3) 동적sql 처리 (0) | 2024.04.05 |
MyBatis(1) 설치 및 설정 (0) | 2024.04.04 |
JDBC(2) 트랜잭션 (0) | 2024.04.04 |
JDBC(1) 기본 + 응용 + 예외처리 (1) | 2024.04.03 |