<< 학습 목표 >>

1. 쿼리 실행 결과로 데이터를 받을 수 있다.

2. 쿼리 실행 결과로 정보를 받을 수 있다.

3. 쿼리 실행 결과로 데이터들을 받을 수 있다.

4. 쿼리 실행 결과로 정보들을 받을 수 있다.


지금까지 과정을 보면 먼저 MyBatis 를 사용해 쿼리를 실행하고 결과를 받아오는 방법에 대해서 간단하게 배웠음 ( https://codingaja.tistory.com/115 ) 그 후 쿼리에 사용할 값에 대해서 자세히 배웠음 ( https://codingaja.tistory.com/116 )

 

이번에는 쿼리를 실행한 후 결괏값을 받는 방법을 배워보자

 

1. SELECT 쿼리를 실행했을 때는 SELECT 쿼리에 맞는 결괏값을 얻을 수 있음

ex) SELECT COUNT(*) AS count FROM member; 쿼리를 실행했다면 결괏값으로 정수를 얻을 수 있음

SELECT * FROM member WHERE nickname = "홍길동"; 쿼리를 실행했다면 결괏값으로 닉네임이 홍길동인 회원의 정보를 얻을 수 있음

SELECT * FROM member; 쿼리를 실행했다면 결괏값으로 회원들의 정보를 얻을 수 있음

 

2. INSERT 쿼리를 실행했을 때는 결괏값으로 정수 1을 얻을 수 있음

3. UPDATE 쿼리를 실행했을 때는 UPDATE 쿼리로 인해 값이 바뀐 행의 개수(정수)를 얻을 수 있음

4. DELETE 쿼리를 실행했을 때는 DELETE 쿼리로 인해 삭제된 행의 개수(정수)를 얻을 수 있음


이제 SELECT 쿼리부터 시작해서 쿼리를 실행한 후 결괏값을 받는 방법을 알아보자

우선 전 글 ( https://codingaja.tistory.com/116 ) 에서 가장 마지막에 사용했던 Member5.xml, MemberDao5, MyBatisController5 파일들을 복사하자

복사한 파일의 이름은 Member6.xml, MemberDao6, MyBatisController6 으로 지정하자

 

 

1. SELECT 쿼리를 실행했을 때는 SELECT 쿼리에 맞는 결괏값을 얻을 수 있음

  1-1. 결괏값이 정수 하나 일 때

더보기

결괏값으로 정수 한 개만 반환하는 쿼리를 작성하자

<?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="com.study.chapter04.MemberDao6">
	<select id="getMemberCount" resultType="_int">
		SELECT COUNT(*) AS count FROM member;
	</select>
</mapper>

 << 코드 설명 >>

(1). 이 쿼리를 실행 하고 나면 결과로 가입된 전체 회원의 수(정수 한 개)가 반환됨
(2). resultType 속성은 이 쿼리를 실행 하고 나면 반환될 값의 타입을 쓰는 것
  (1)에서 설명했듯 이 쿼리를 실행 하고 나면 정수가 반환 될 것이기에 정수(int)의 별칭인 _int 로 명시했음
  주의 할 점은 resultType="int" 로 쓰면 안됨
  int는 Integer의 별칭이고 _int는 int의 별칭임
  만약 Integer와 int에 대해서 잘모른다면 자바의 래퍼(Wrapper) 클래스에 대해서 다시 봐야함

 

이번에는 쿼리와 매칭될 DAO에 메서드를 선언하자

package com.study.chapter04;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MemberDao6 {
	int getMemberCount();
}

<< 코드 설명 >>

MemberDao6의 getMemberCount 메서드와 매치될 쿼리가 정수를 반환하므로 이 메서드의 반환 타입도 정수여야함

 

 

이번에는 컨트롤러를 만들자

package com.study.chapter04;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MyBatisController6 {
	@Autowired
	private MemberDao6 memberDao;
	
	@GetMapping("/chapter04/mybatis/v6/member/count")
	public void getMemberCount(SelectMemberDto selectMemberDto) {
		int count = memberDao.getMemberCount();
		
		System.out.println("가입된 전체 회원의 수 => " + count);
	}

}

 

이와 같이 SELECT 쿼리의 실행 결과가 정수 하나라면 select 태그의 resultType을 _int 로 명시해야하고 해당 쿼리와 매칭될 DAO 메서드는 반환 타입이 int 여야함

 

또한 SELECT 쿼리의 실행 결과가 정수 하나 외에 실수 하나, 문자열 하나 등 데이터 하나라면 select 태그의 resultType 속성의 값으로 그 데이터에 맞는 타입 명을 명시해줘야함

그리고 DAO의 메서드는 반환 타입으로 데이터에 맞는 타입을 써줘야함


  1-2. 결괏값이 한 행(정보 하나) 일 때

더보기

결괏값으로 정보 한 개만 반환하는 쿼리를 작성하자

<?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="com.study.chapter04.MemberDao6">
	// ...
    
	<select id="getMemberByNickname" parameterType="string" resultType="com.study.chapter04.SelectMemberDto">
		SELECT * FROM member WHERE nickname = #{nickname};
	</select>
    
	// ...
</mapper>

( 쿼리가 점점 길어지므로 지금 상황에 필요한 쿼리만 가져왔음 )

<< 코드 설명 >>

(1). 이 쿼리는 해당 닉네임을 사용하는 회원 정보를 조회하므로 이 쿼리의 결과는 회원 정보 하나(한 행)임
(2). 이 쿼리에 사용할 값이 닉네임(문자열)이므로 parameterType 속성 값은 String의 별칭인 string으로 명시
(3). 이 쿼리의 결과가 회원 정보이므로 회원 정보를 받을 수 있는 DTO를 resultType 속성 값으로 명시

 

 

이번에는 쿼리와 매칭될 DAO에 메서드를 선언하자

package com.study.chapter04;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MemberDao6 {
	// ...
    
	SelectMemberDto getMemberByNickname(String nickname);
    
	// ...
}

<< 코드 설명 >>

MemberDao6의 getMemberByNickname 메서드와 매치될 쿼리가 SelectMemberDto(회원 정보 하나)를 반환하므로 이 메서드의 반환 타입도 똑같이 SelectMemberDto여야함

 

 

이번에는 컨트롤러를 만들자

package com.study.chapter04;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MyBatisController6 {
	@Autowired
	private MemberDao6 memberDao;
	
	// ...
	
	@GetMapping("/chapter04/mybatis/v6/member")
	public void getMemberByNickname(String nickname) {
		SelectMemberDto member = memberDao.getMemberByNickname(nickname);
		
		System.out.println("<< 닉네임이 [ " + nickname + " ] 인 회원의 정보 >>");
		System.out.println(member);
	}

	// ...
}

 

 

이와 같이 SELECT 쿼리의 실행 결과가 정보 하나라면 select 태그의 resultType을 정보를 받을 수 있는 DTO 로 명시해야하고 해당 쿼리와 매칭될 DAO 메서드의 반환 타입은 동일한 DTO로 지정해주면됨


  1-3. 결괏값이 여러 행(데이터들) 일 때

더보기

결괏값으로 문자열들(여러 행 / 데이터들)을 반환하는 쿼리를 작성하자

<?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="com.study.chapter04.MemberDao6">
	// ...
	
	<select id="getAllMemberNickname" resultType="string">
		SELECT nickname FROM member;
	</select>
    
	// ...
</mapper>

<< 코드 설명 >>

(1). 이 쿼리를 실행하면 모든 회원들의 닉네임(문자열들)을 반환하므로 resultType은 string 으로 명시함

 

 

이번에는 쿼리와 매칭될 DAO에 메서드를 선언하자

package com.study.chapter04;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;


@Mapper
public interface MemberDao6 {
	// ...
    
	List<String> getAllMemberNickname();
 
	// ...
}

<< 코드 설명 >>

앞서 [ 결괏값이 정수 하나 일 때 ], [ 결괏값이 한 행(정보 하나) 일 때 ] 는 resultType과 DAO 메서드의 반환 타입을 맞춰줬는데 [ 결괏값이 여러 행(데이터들) 일 때 ] 는 resultType과 DAO 메서드의 반환 타입이 다름

 

결국 MyBatis는 SELECT nickname FROM member; 쿼리를 실행한 후 결과를 DAO 메서드의 반환 타입에 맞춰서 문자열들을 반환함

 

 

이번에는 컨트롤러를 만들자

package com.study.chapter04;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MyBatisController6 {
	@Autowired
	private MemberDao6 memberDao;
	
	// ...

	@GetMapping("/chapter04/mybatis/v6/member/nicknames")
	public void getAllMemberNickname() {
		List<String> nicknameList = memberDao.getAllMemberNickname();
		
		for(String nickname : nicknameList) {
			System.out.println(nickname);
		}
	}
    
	// ...
}

( 코드 설명이 필요 없을 정도로 간단하므로 코드 설명은 생략함 )

 

 

이와 같이 SELECT 쿼리의 실행 결과가 데이터들이라면 select 태그의 resultType은 데이터 타입으로 명시해야하고 해당 쿼리와 매칭될 DAO 메서드는 반환 타입이 List<데이터타입> 여야함


  1-3. 결괏값이 여러 행(정보들) 일 때

더보기

결괏값으로 회원들의 정보(여러 행 / 정보들)을 반환하는 쿼리를 작성하자

<?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="com.study.chapter04.MemberDao6">
	// ...
	
	<select id="getAllMember" resultType="com.study.chapter04.SelectMemberDto">
		SELECT * FROM member;
	</select>
    
	// ...
</mapper>

 << 코드 설명 >>

이 쿼리를 실행하면 회원들의 정보를 반환하므로 resultType 속성 값은 회원 정보를 담을 수 있게 DTO로 명시해야함

 

 

이번에는 쿼리와 매칭될 DAO에 메서드를 선언하자

package com.study.chapter04;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MemberDao6 {
	// ...
    
	List<SelectMemberDto> getAllMember();
    
	// ...
}

<< 코드 설명 >>

앞서 [ 결괏값이 여러 행(데이터들) 일 때 ] 와 마찬가지로 resultType과 DAO 메서드의 반환 타입이 다름

 

결국 MyBatis는 SELECT * FROM member; 쿼리를 실행한 후 결과를 DAO 메서드의 반환 타입에 맞춰서 회원 정보들을 반환함

 

 

이번에는 컨트롤러를 만들자

package com.study.chapter04;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MyBatisController6 {
	@Autowired
	private MemberDao6 memberDao;
	
	// ...
	
	@GetMapping("/chapter04/mybatis/v6/members")
	public void getAllMember() {
		List<SelectMemberDto> memberList = memberDao.getAllMember();
		
		for(SelectMemberDto member : memberList) {
			System.out.println(member);
		}
	}
    
	// ...
}

( 코드 설명이 필요 없을 정도로 간단하므로 코드 설명은 생략함 )

 

 

이와 같이 SELECT 쿼리의 실행 결과가 정보들이라면 select 태그의 resultType은 정보를 담을 수 있는 DTO로 명시해야하고 해당 쿼리와 매칭될 DAO 메서드는 반환 타입이 List<DTO타입> 이여야함



2. INSERT 쿼리를 실행했을 때는 결괏값으로 정수 1을 얻을 수 있음

이번에는 INSERT 쿼리를 작성하고 결괏값을 받아 보자

 

아래와 같이 Member6.xml 파일에 INSERT 쿼리를 추가하자

<?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="com.study.chapter04.MemberDao6">
	// ...
	
	<insert id="joinMember" parameterType="com.study.chapter04.InsertMemberDto">
		INSERT INTO member(id, pw, nickname, tel) VALUES(#{id}, #{pw}, #{nickname}, #{tel});
	</insert>
    
	// ...
</mapper>

<< 코드 설명 >>

SELECT와 연계해서 생각해보면 특이한 점이 있음

SELECT에서는 쿼리 결과가 정수 하나 라면 resultType 속성 값을 _int 로 명시해야했음

INSERT 쿼리 결과는 정수 1 이라고 했으므로 insert 태그에 resultType 속성 값을 _int 로 명시해야함

그러나 insert 태그에는 resultType 속성을 쓸 수 없음

insert 태그에는 resultType을 쓰지 않아도 insert 쿼리의 결과로 정수 1을 반환함

 

 

이번에는 INSERT 쿼리와 매치될 DAO 메서드를 추가하자

package com.study.chapter04;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MemberDao6 {
	// ...
    
	int joinMember(InsertMemberDto newMember);
    
	// ...
}

<< 코드 설명 >>

알고 있듯이 이 메서드를 호출했을 때 실행되는 쿼리가 정수 1을 반환하므로 정수를 받을 수 있게 반환 타입을 int로 지정했음

만약, INSERT 쿼리가 반환하는 정수 1이 필요 없으면 메서드의 반환 타입을 void 로 해도됨

 

 

이번에는 컨트롤러를 추가하자

package com.study.chapter04;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class MyBatisController6 {
	@Autowired
	private MemberDao6 memberDao;
	
	// ...
	
	@PostMapping("/chapter04/mybatis/v6/member")
	public void joinMember(InsertMemberDto newMember) {
		int result = memberDao.joinMember(newMember);
		
		if(result == 1) {
			System.out.println("회원 가입 성공");
		} else {
			System.out.println("회원 가입 실패");
		}
	}
    
	// ...
}

( 코드 설명이 필요 없을 정도로 간단하므로 설명은 생략함 )


3. UPDATE 쿼리를 실행했을 때는 UPDATE 쿼리로 인해 값이 바뀐 행의 개수(정수)를 얻을 수 있음

4. DELETE 쿼리를 실행했을 때는 DELETE 쿼리로 인해 삭제된 행의 개수(정수)를 얻을 수 있음

 

이번에 배울건 설명이 필요 없을 정도로 간단하니 코드만 첨부하겠음

 

<< 회원 정보 수정(UPDATE 쿼리), 삭제(DELETE 쿼리) 쿼리 >>

<?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="com.study.chapter04.MemberDao6">
	// ...
	
	<update id="updateMember" parameterType="com.study.chapter04.InsertMemberDto">
		UPDATE member SET pw = #{pw}, nickname = #{nickname}, tel = #{tel} WHERE id = #{id}
	</update>
	
	<delete id="deleteMember" parameterType="com.study.chapter04.DeleteMemberDto">
		DELETE FROM member WHERE id = #{id} AND pw = #{pw}
	</delete>
    
	// ...
</mapper>

 

<< DAO >>

package com.study.chapter04;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MemberDao6 {
	// ...
    
	int updateMember(InsertMemberDto newMember);
	int deleteMember(DeleteMemberDto targetMember);
    
	// ...
}

 

<< 컨트롤러 >>

package com.study.chapter04;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;

@Controller
public class MyBatisController6 {
	@Autowired
	private MemberDao6 memberDao;
	
	// ...
	
	@PutMapping("/chapter04/mybatis/v6/member")
	public void updateMember(InsertMemberDto newMember) {
		int result = memberDao.updateMember(newMember);
		
		if(result == 1) {
			System.out.println("회원 정보 수정 성공");
		} else {
			System.out.println("회원 정보 수정 실패");
		}
	}
	
	@DeleteMapping("/chapter04/mybatis/v6/member")
	public void deleteMember(DeleteMemberDto targetMember) {
		int result = memberDao.deleteMember(targetMember);
		
		if(result == 1) {
			System.out.println("회원 정보 삭제 성공");
		} else {
			System.out.println("회원 정보 삭제 실패");
		}
	}
    
	// ...
}

여기서 주의할 점은 INSERT 쿼리는 무조건 정수 1만 반환하지만 UPDATE, DELETE는 쿼리로 영향을 받은 행의 수를 반환함

INSERT 쿼리와 공통점은 UPDATE, DELETE 쿼리로 영향 받은 행의 수를 사용하지 않는다면 DAO 메서드의 반환 타입을 void 로 지정하면 됨

728x90
LIST