[신세계I&C KDT][Java 프로그래밍] #17 MyBatis 프레임워크 (0404)

박현아·2024년 4월 4일
0

신세계아이앤씨 KDT

목록 보기
21/42

1. MyBatis 프레임워크

1) 개요

  • JDBC 사용을 편리하고 효율적으로 할 수 있는 기능이 추가된 형태의 SQL mapping 프레임워크

2) jar 다운로드
http://mybatis.org > mybatis-3.5.14 > assets > mybatis-3.5.14.zip 다운

3) 압축 풀기
mybatis-3.5.14.jar (build path 대상임)
mybatis-3.5.14.pdf (매뉴얼, https://mybatis.org/mybatis-3/)

4) 이클립스에서 build path
(1) 프로젝트 생성
(2) 2개의 jar 파일 build path
- mysql-connector-j-8.jar (mysql 드라이버)
- mybatis-3.5.14.jar

  • 자바프로젝트 선택 > 오른쪽 클릭 > build path > configure build path > 3번째 탭 libraries > classpath 선택하고 오른쪽 항목에서 Add External jars.. 클릭 > mysql-connector-j-8.3.0.jar 와 mybatis-3.5.14.jar 선택

2. MyBatis 사용 방법

1) jdbc.properties 파일 생성

: JDBC에서 사용했던 4가지 정보를 외부 파일에 저장
-> 파일 추가 - jdbc.properties
-> src 폴더에 저장 (패키지 설정 가능 - com.config)

cf) 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
(띄어쓰기 X)

2) xml 파일 추가

: 최소 2개의 xml 파일이 필요하다
-> *.xml

(1) XXXMapper.xml 생성 (mapper 파일)

  • 용도 : JDBC에서 사용했던 SQL 문을 저장하는 파일

  • 테이블 당 하나씩 작성

  • XXXMapper.xml 형식으로 만들기

  • com.config 패키지에 저장

  • 예> DeptMapper.xml

<!-- namespace가 패키지같은 역할을 한다 -->
<mapper namespace="com.config.DeptMapper">
  
  	<!-- 전체 조회 -->
  	<select id="findAll" resultType="DeptDTO">
  		select deptno, dname, loc 
  		from dept
  		order by deptno desc
  	</select>
  	
  	<!-- 조건 조회 select는 꼭 resultType 설정해줘야됨 parameterType은 해시블럭에 들어가는 타입 설정해주는 것-->
  	<select id="findByDeptno" resultType="DeptDTO" parameterType="int">
  		select deptno, dname, loc
  		from dept
  		where deptno = #{deptno} <!-- mapper는 해시 블럭 #{ } -->
  	</select>
  	
  	<!-- 조건 조회 2 -->
  	<select id="findByDnameOrLoc" resultType="DeptDTO" parameterType="DeptDTO">
  		select deptno, dname, loc 
  		from dept
  		where dname = #{dname} or loc = #{loc} <!-- 이 때는 DeptDTO의 변수명으로 써줘야됨 -->
  	</select>
  	
  	<!-- 조건 조회 3 -->
  	<select id="findByDnameOrLoc2" resultType="DeptDTO" 
  	parameterType="hashmap">
  		select deptno, dname, loc 
  		from dept
  		where dname = #{x} or loc = #{y} <!-- hashmap은 키값으로 써줘야됨-->
  	</select>
  	
</mapper>
  • DeptMapper2.xml
<mapper namespace="com.config.DeptMapper2">
  
  	<!-- 삭제 -->
  	<delete id="remove" parameterType="int">
  		delete
  		from dept
  		where deptno = #{deptno}
  	</delete>
  	<delete id="removeByDname" parameterType="string">
  		delete
  		from dept
  		where dname = #{dname}
  	</delete>
  
  	<!-- 수정 -->
  	<update id="update" parameterType="DeptDTO">
  		update dept 
  		set dname = #{dname}, loc = #{loc}
  		where deptno = #{deptno}
  	</update>
  
  	<!-- 저장 -->
  	<insert id="save" parameterType="DeptDTO">
  		insert into dept (deptno, dname, loc)
  		values (#{deptno}, #{dname}, #{loc})
  	</insert>
  	<insert id="save2" parameterType="DeptDTO">
  		insert into dept (deptno, dname)
  		values (#{deptno}, #{dname})
  	</insert>
  
  	<!-- 전체 조회 -->
  	<select id="findAll" resultType="DeptDTO">
  		select deptno, dname, loc 
  		from dept
  		order by deptno asc
  	</select>

</mapper>

(2) Configuration.xml 생성 (설정 파일)

  • 용도 : mybatis 사용시 환경설정 정보들 관리 (DB 연동 정보, DTO 별칭, mapper 등록)
  • Configuration.xml
  • com.config 패키지에 저장
  • XXXMapper.xml 작성 후 꼭 Configuration.xml에 mapper 등록해주기 !!!
  • 예> Configuration.xml
<configuration>

<!-- jdbc.properties 등록 (driver, url, userid, passwd) -->
<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">
        <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>
  <!-- Mapper.xml 등록 -->
    <mapper resource="com/config/DeptMapper.xml"/>
    <mapper resource="com/config/DeptMapper2.xml"/>
    
    <mapper resource="com/config/EmpMapper.xml"/>
</mappers>
  
</configuration>

3) MySqlSessionFactory.java 생성

: Configuration.xml 파일을 읽는 자바 코드가 필요하다

  • 예> MySqlSessionFactory.java
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;
}

cf) JDBC vs MyBatis

(1) JDBC에서 필요한 API

  • Connection
  • PreparedStatement
  • ResultSet

(2) MyBatis에서 필요한 API

  • SqlSessionFactory
  • SqlSession ★
    -> SqlSession session = MySqlSessionFactory.getSession();

4) 하나의 레코드를 저장하는 DTO 작성 ★

  • 역할 : select 된 결과인 레코드를 자동으로 DTO에 저장한다
    단, 연결 고리가 존재한다. 테이블의 컬럼명 (원칙은 컬럼 헤더값)과 DTO의 변수명이 일치해야 된다

  • 예> DeptDTO.java

public class DeptDTO {

	int deptno;
	String dname;
	String loc;
	
	public DeptDTO() {
	}
	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 + "]";
	}
}
}

cf) parameterType = "전달할 파라미터 타입" 의 종류
https://mybatis.org/mybatis-3/configuration.html#typealiases

5) 별칭 지정하기

예> com.dto.DeptDTO -> DeptDTO (별칭)로 지정
-> Configuration.xml에서 별칭 지정하고 Mapper에서 별칭을 사용한다

문법:

<!-- DTO 별칭 -->
<typeAliases>
	<typeAlias type="com.dto.DeptDTO" alias="DeptDTO" />
	<typeAlias type="com.dto.EmpDTO" alias="EmpDTO" />
</typeAliases>

6) SqlSession의 메서드

-> DeptMapper.xml에 있는 태그를 호출하는 작업

(1) select 작업

-단일 레코드 반환
DeptDTO dto = session.selectOne("mapper의 id값");
DeptDTO dto = session.selectOne("mapper의 id값", Object obj); // obj는 where절에 사용하는 값
-다중 레코드 반환
List\ list = sessiono.selectList("mapper의 id값"):
List\ list = sessiono.selectList("mapper의 id값", Object): // obj는 where절에 사용하는 값

(2) insert 작업

int n = session.insert("namespace명.mapper의 id값");
int n = session.insert("namespace명.mapper의 id값", Object obj); // obj는 저장할 데이터

(3) update 작업

int n = session.update("namespace명.mapper의 id값");
int n = session.update("namespace명.mapper의 id값", Object obj); // obj는 수정할 데이터

(4) delete 작업

int n = session.delete("namespace명.mapper의 id값");
int n = session.delete("namespace명.mapper의 id값", Object obj); // obj는 삭제할 데이터

7) Main 작성

(1) 순서

  1. SqlSession 열기
  2. SqlSession의 메서드를 이용해서 DeptMapper.xml (XXXMapper.xml)과 연동
    -> Mapper.xml의 namespace.id값과 resultType값 <> 필요
  3. 조회
  4. 출력
  5. close 작업

(2) 예시

  • MyBatisDeptMain.java (DeptMapper.xml 참조)
public class MyBatisDeptMain {
	public static void main(String[] args) {

		// 1. SqlSession 열기
		SqlSession session = MySqlSessionFactory.getSession();
		
		// 2. SqlSession의 메서드를 이용해서 DeptMapper.xml과 연동
		// DeptMapper.xml의 id값 과 resultType 값 <>
		
        // 1) 전체 조회
		List<DeptDTO> list = session.selectList("findAll"); 
        
		// 2) 조건 조회 1
		DeptDTO xxx = session.selectOne("findByDeptno", 10);
		
		// 3) 조건 조회 2
		DeptDTO yyy = new DeptDTO();
		yyy.setDname("인사과");
		yyy.setLoc("인천");
		List<DeptDTO> list2 = session.selectList("findByDnameOrLoc", yyy );
		
		// 4) 조건 조회 3 (hashMap 이용)
		HashMap<String, String> map = new HashMap<>();
		map.put("x", "인사과");
		map.put("y", "서울");
		List<DeptDTO> list3 = session.selectList("findByDnameOrLoc2", map ); 
		
		// 3. 출력
		System.out.println(list3);
        
        // 4. close 작업
        session.close();
	}
}
  • MyBatisDeptMain2_DML.java (DeptMapper2.xml 참조)
public class MyBatisDeptMain2_DML {
	public static void main(String[] args) {
		  
		// 1. SqlSession 열기
		SqlSession session = MySqlSessionFactory.getSession();
		
		// 데이터 저장
		DeptDTO dto = new DeptDTO(3, "개발", "서울");
		// 첫 번째엔 mapper 아이디
		int n = session.insert("com.config.DeptMapper2.save", dto);
		session.commit(); // ************
		
		// 데이터 수정
		DeptDTO dto2 = new DeptDTO(1, "백엔드개발", "서울");
		int n2 = session.update("com.config.DeptMapper2.update", dto2);
		session.commit();
		
		// 데이터 삭제 
		String dname = "개발";
		int n3 = session.delete("com.config.DeptMapper2.removeByDname", dname);
		session.commit();
		
        // 전체 조회
		List<DeptDTO> list = session.selectList("com.config.DeptMapper2.findAll");
		System.out.println(list);
		
		// 4. close 작업
		session.close();
	}

}

3. MyBatis 동적 sql 처리

1) 다중 insert 처리

- mysql sql문

insert into emp (empno, ename, sal)
values (10, 'a', 100), (20, 'b', 200), (),...; 

- mybatis sql문

  • EmpMapper.xml
<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>
  • Configuration.xml
<mappers>
  <!-- DeptMapper.xml 등록 -->
    <mapper resource="com/config/DeptMapper.xml"/>
    <mapper resource="com/config/DeptMapper2.xml"/>
    
    <mapper resource="com/config/EmpMapper.xml"/>
</mappers>
  • MyBatisEmpMain.java
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();
	}
}

2) 다중 delete 처리

- mysql sql문

delete from emp
where sal IN ( 800, 1000, .. );

- mybatis sql문 1

: 무조건 sal 전달됨

<delete id="remove" parameterType="arraylist">
delete from emp
where sal IN
<foreach item="x" collection="list" open="(" separator="," close=")"> 
#{x}
</foreach>

mybatis sql문 2

: sal 전달안될수도 있는 경우.

<delete id="remove" parameterType="arraylist">
delete from emp
<where>
<foreach item="x" collection="list" open="sal IN (" separator="," close=")">
#{x}
</foreach>
<where>

3) 다중 update 문

- mysql문

update emp
set sal = sal +100
where empno in (800, 1000,...);

- mybatis sql문

<update id="update" parameterType="arraylist">
  update emp
  set sal = sal +100
  <where>
    <foreach item="X" collection="list" open="empno in (" separator = "," close=")">
      	#{X}
    </foreach>
  </where>
</update>

4) 선택적 update 문

- mysql sql문

: 어떤 컬럼을 수정할지 잘 모르는 경우
update emp
set sal = 값
set ename = 값
set sal = 값, ename = 값
where empno = 값;

- mybatis sql문

update emp

sal=#{sal},
ename=#{ename}

where empno = 값

5) 조건이 여러 개일 때

job 이 'MANAGER' 인 경우 sal > 1500 조회
job 이 'SALESMAN' 인 경우 sal > 2500 조회
모두 아니면 sal > 3000 조회

- mybatis sql문

select 
from emp
<where>
  <choose>
    <when test="job == 'manager'"> sal>1500 </when>
    <when test="job == 'salesman'"> sal>2500 </when>
    <otherwise> sal>3000 </otherwise>
  </choose>
 </where>

6) 단일값 조회

select count(*)
from emp;

  • JDBC 이용:
rs.next();
rs.getInt(1);  // rs.getInt("cnt")
  • MyBatis 이용
<select id="cnt"  resultType="int">
int cnt =session.selectOne("cnt");

7) 페이징 처리

(1) 내림차순 정렬

<select id="paging" resultType="EmpDTO">
	select empno, ename, sal
	from emp
	order by empno desc
</select>

(2) selectList("", 파라미터, new RoundBounds(skip, 갯수) )

예>

int curPage = 2;
int perPage = 3; // 페이지당 보여줄 레코드 개수
int skip = (curPage-1) * perPage;
		
List<EmpDTO> list7 = session.selectList("com.config.EmpMapper.paging", null, 
		                           new RowBounds(skip, perPage));

cf) CDATA 섹션
: XML 문법
: CDATA (Character DATA) 표현식

<![CDATA[
SQL문
]]>

<!-- 참고 -->
> : &gt;
<  : &lt;
공백: &nbsp;
"  : &quot;

0개의 댓글