국비교육(22-23)

50일차(1)/Spring(4) : MyBatis 설치 / DB 데이터 불러오기 (getList)

서리/Seori 2022. 12. 17. 21:20

50일차(1)/Spring(4) : MyBatis 설치 / DB 데이터 불러오기 (getList)

 

-  JndiObjectFactoryBean, SqlSessionFactoryBean, SqlSessionTemplate 간의 관계

- @Autowired를 사용한 의존객체 주입(DI)

- Configuration.xml, Mapper 문서 작성방법

 

 

- 만약 이클립스가 좀 느리다면... 설치폴더에서 구성 설정 파일을 찾는다.

- 저 부분이 메모리 사이즈인데, 숫자를 크게 해주면 빨라진다.

 

- 예전에 했던 프로젝트를 사용하지 않는다면 close project 해서 메모리 사용량을 줄일 수도 있다.

 (나중에 더블클릭하면 살아난다)

 


 

★복습 필요

 

Spring02_MyBatis  MVC프로젝트 생성

com.sy.spring02 패키지생성

 

- Mybatis를 사용하면 간편하게 Dao를 만들 수 있다. Dao의 소스코드가 크게 줄어든다.

 

 

pom.xml

- pom.xml에 저장해놓은 내용

- mybatis에 필요한 의존객체들, DB연동을 위한 라이브러리들. 미리 넣어준 것이다.

 (아래 오라클 라이브러리도 있다.)

 

- 이 파일들이 들어있어야 mybatis, DB 를 사용할 수 있다.

 

 

WEB-INF - web.xml

 

- 이 DispatcherServlet이 동작하면서 Spring이 작동한다.

 


 

servlet-context.xml

- 핵심 의존 객체의 생성과 관리를 이곳에서 맡아서 해준다.

- 어떤 것을 객체로 설정할지 기준을 만들어준다. 이 문서를 바탕으로 객체를 생성한다.

ex) 이미지는 저 객체를 생성해서 id="dataSource" 라는 이름으로 관리한다는 의미이다.

 

- DB 연동을 하기 위해서는 이렇게 3가지 객체가 필요하다.

 

- 이 xml의 내용이 곧 아래의 자바 코드라고 생각하면 된다.

 

- 객체를 생성하고, setter 메소드를 호출하면서 문자열을 전달하는 것이다.(value를 사용해서 전달한다)

 

- ref를 지우고 확인해보면 해당 위치에 콩 모양의 DataSource가 자동완성되는것을 볼 수 잇다.

 

- ref 를 사용해 이곳에 생성된 객체를 넣어주는 것이다.

- JndiObjectFactoryBean → SqlSessionFactoryBean → SqlSessionTemplate 에 각각 값을 넣어줌

- 최종적으로는 SessionTemplate 객체에 들어가고, 이 객체를 dao에서 사용한다.

- Spring이 관리하는 bean 컨테이너 안에 있다가 dao에 적어주면 Autowired로 객체가 자동 주입된다.

 

- servlet-context.xml 에서 특정 객체를 생성해서 bean 으로 관리하도록 할 수 있다.

 

 

- 또한 객체의 조립도 할 수 있다.(조립이란 의존성 주입(DI)을 말한다.)

 

- 만약 servlet-context.xml 안에 이렇게 넣어준다면 Spring이 시작될 때 MemberDto 객체를 생성해서 관리하게 된다.

 

property name="num" == mem1.setNum(1) 

- mem1이라는 이름으로 객체를 생성해서 관리하는 것! value 값에는 숫자, 문자를 넣어주면 된다.

 

- 이런 식으로 작성하면 spring에서 MemberDto 객체를 만들어 관리하게 할 수도 있다.

 

- SqlSessionFactoryBean 객체 (myBatis를 위해 필요한 객체)
- 이 객체를 사용하려면 Configuration.xml 문서가 어디에 있는지 알려야 한다. 
- value 에서 classpath: 는 src/main/resources 폴더를 가리킨다.
- 따라서 classpath:Configuration.xml 라는 말은 Configuration.xml 파일이 src/main/resources 폴더 안에 존재해야 한다는 의미!

 

 

- 이것이 SessionTemplate으로 넘어간다. (생성자의 인자로 전달한다)

- 이 SessionTemplate 객체가 관리되다가 필요할때 Dao에 주입(injection) 되는 것이다.

 (인터페이스를 구현했기때문에 sqlSession 타입으로 주입된다.)

 

- 이렇게 복잡하게 만든 이유는?! 의존관계를 느슨하게 해서 유지보수를 편하게 하기 위해...

 

- component scan을 통해서 bean 을 자동으로 생성하게 할 수도 있다.

 

 


 

- Help- Eclipse Marketplace에서 설치

 

*myBatis : https://mybatis.org/

- myBatis 사용방법 참고

 

 

- Java Resources-src/main/resources 폴더 안에 other-xml-xml파일 생성

 

Configuration.xml

<?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>
	<!-- sql 문을 작성한 Mapper xml 문서가 어디에 있는지 목록을 작성해야 한다. -->
	<mappers>
		<mapper resource="mapper/MemberMapper.xml"/>
	</mappers>
</configuration>

 

- doctype이 결정되어 있기 때문에, 안에 적을 수 있는 내용이 한정되어 있다.(특정 문서 형식으로 작성하는 것이 강제된다)

- 여기의 최상위 요소는 <configuration>이다. 그렇게 정해져 있다.

- <mapper> 에서는 myBatis에서 사용하는 Mapper가 어디에 있는지 알려주면 된다.

 

- 이 mapper안에서 어떤 속성들을 작성할 수 있는지 배우는 것이 myBatis를 배우는 것이다.

 

 

- servlet-context.xml 안에 붙여넣기

   <!-- 
      JNDI 데이터 소스 객체 얻어오는 설정   
      Servers/context.xml 에 설정된 oracle 접속정보 가 있어야 된다. 
       
      <Resource name="jdbc/myoracle" auth="Container"
              type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
              url="jdbc:oracle:thin:@127.0.0.1:1521:xe"
              username="scott" password="tiger" maxTotal="20" maxIdle="10"
              maxWaitMillis="-1"/>          
   -->
   <beans:bean id="dataSource" 
      class="org.springframework.jndi.JndiObjectFactoryBean">
      <beans:property name="jndiName" value="java:comp/env/jdbc/myoracle"/>
   </beans:bean>
   
   <!-- 
      위는 아래의 코드와 같다
      dataSource = new JndiObjectFactoryBean();
      dataSource.setJndiName("java:comp/env/jdbc/myoracle");
    -->
   
   
   <!-- 
      SqlSessionFactory 객체 
      Configuration.xml 문서가 어디에 있는지 알려야 한다. 
   -->
   <beans:bean id="sessionFactory" 
      class="org.mybatis.spring.SqlSessionFactoryBean">
      <beans:property name="dataSource" ref="dataSource"/>
      <beans:property name="configLocation"
   value="classpath:Configuration.xml"/>
   </beans:bean>
   <!-- 
      sessionFactory=new SqlSessionFactoryBean();
      sessionFactory.setDataSource(dataSource);
      sessionFactory.setConfigLocation("classpath:com/gura/xxx");
    -->
   

   <!-- 
      SqlSession 인터페이스를 구현한 
      SqlSessionTemplate(SqlSession) 객체 
      Dao 가 의존하는 객체 
   -->
   <beans:bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
      <beans:constructor-arg name="sqlSessionFactory" 
         ref="sessionFactory"/>
   </beans:bean>
   
   
   
   <!-- 
      위의 bean 설정을 java code 로 환산 하면 아래와 같다 
      
      dataSource = new JndiObjectFactoryBean();
      dataSource.setJndiName("java:comp/env/jdbc/myoracle");
      
      sessionFactory=new SqlSessionFactoryBean();
      sessionFactory.setDataSource(dataSource);
      sessionFactory.setConfigLocation("classpath:xxx");
      
      new SqlSessionTemplate(sessionFactory);
    -->

 

 

 

- JDBC에 bean이 동작하게 하기 위해 Tomcat Server의 context.xml 에 내용을 넣어주어야 한다.

 

- 내 오라클에 접속하기 위한 설정!

 

- servlet-context.xml 안에 붙여넣은 내용

- 여기에서 경로를 지정해놓아야 DB에서 데이터를 요청할 때 찾아다가 쓸 수 있는 것이다.

 

- SessionFactory에는 classpath: 정보가 들어있다. 여기에 위치시켜 놓았다고 알리는 것!

- 저 classpath: 의 위치가 /resources/ 폴더라고 보면 된다.

 


 

- Java Resources-src/main/resources 폴더 안에 mapper 폴더만들기

mapper/ MemberMapper.xml 생성

<?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="member">
	<!-- 
		여기서 resultType은 select 된 row를 어떤 객체에 담을지를 결정하는 것이다.
		dto로 설정했다면
		SELECT num, name, addr 의 칼럼명과
		dto의 필드명이 반드시 일치해야 정상 동작을 한다. 
	-->
	<select id="getList" resultType="com.sy.spring02.member.dto.MemberDto">
		SELECT num, name, addr
		FROM member
		ORDER BY num ASC	
	</select>
</mapper>

 

- others- mapper으로 생성할 수 있다

 

 

- myBatis가 설치되어 있다면 MyBatis 폴더 안의 XML Mapper로 생성할 수도 있다.

 

- mapper 요소를 ctrl+space 자동완성으로 작성할 수 있다.

- <mapper> 안쪽은 sql문으로 작성한다.

 

- configuration에 mapper의 위치를 알려주어야 한다. 자동완성으로 이렇게 추가 가능!

<mappers>
    <mapper resource="mapper/MemberMapper.xml"/>
</mappers>

 

- src/main/resources 안에 Configuration.xml 파일

- 하위폴더 mapper에 MemberMapper.xml 파일

 이 구조로 만들어주기!

 


 

com.sy.spring02 의 하위에 member.dto / dao / controller 패키지 각각 생성

 

MemberDao 만들기 (인터페이스)

package com.sy.spring02.member.dao;

import java.util.List;

import com.sy.spring02.member.dto.MemberDto;

public interface MemberDao {
	public void insert(MemberDto dto);
	public void update(MemberDto dto);
	public void delete(int num);
	public MemberDto getData(int num);
	public List<MemberDto> getList();
}

 

MemberDaoImpl.java (클래스) - 아직 getList만 작성한 상태

package com.sy.spring02.member.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.sy.spring02.member.dto.MemberDto;

// component scan 을 통해서 spring 이 관리하는 bean 이 될수 있도록 어노테이션 붙여놓기
@Repository
public class MemberDaoImpl implements MemberDao{
   
   @Autowired
   private SqlSession session; // select, insert, update, delete 작업을 하기 위한 핵심 의존 객체
   
   @Override
   public void insert(MemberDto dto) {
      // TODO Auto-generated method stub
      
   }

   @Override
   public void update(MemberDto dto) {
      // TODO Auto-generated method stub
      
   }

   @Override
   public void delete(int num) {
      // TODO Auto-generated method stub
      
   }

   @Override
   public MemberDto getData(int num) {
      // TODO Auto-generated method stub
      return null;
   }

   @Override
   public List<MemberDto> getList() {
      /*
       * mapper's namespace => member
       * sql's id => getList
       * resultType => MemberDto
       * return Type => List
       */
      List<MemberDto> list=session.selectList("member.getList");
      
      return list;
   }

}

 

@Repository

- component scan 을 통해서 spring 이 관리하는 bean 이 될 수 있도록 어노테이션 붙여놓기!

- bean이 되려면 annotation이 붙어 있어야 한다. 저게 붙어있으면 bean이 된다.

 

 

sevlet-context.xml

- SqlSessionTemplate 객체에 Dao가 의존하는 구조가 된다.

- dao에 객체가 injection이 되어야 한다.

 

** bean이 되는 두가지 방법

1) 컴포넌트 스캔으로 bean되기

2) xml문서로 정의해서 bean되기

 

- SqlSessionTemplate 은 class 인데 SqlSession 인터페이스을 구현한 타입이다.

- 이 객체가 DI 될 수 있도록 MemberDaoImpl에서 설정해야 한다.

 

- servlet-context 에 설정되어 있기 때문에, MemberDaoImpl 에서 요청하면 바로 객체가 주입된다.

 

 

- SqlSession 타입의 session 필드를 만들어서 @Autowired 를 붙여주면 bean을 spring에서 알아서 주입해준다.

- SqlSession은 Dao의 메소드 작업을 하기 위한 핵심 의존 객체이다.

 

- MemberDao 에서 getList() 를 작성해보기. dao를 이렇게만으로도 작성할 수 있다.

(session 을 사용하면 알아서 객체가 들어오므로, 객체를 따로 생성해주는 과정이 필요없다.)

- 단 sql문은 따로 작성해야 한다.

 

- 변수의 타입이 List<>이면 무조건 session.selectList() 이다.

 

- session.에서 점을 찍어보면 SELECT문만 11개 정도 있다. 제일 많이 사용하는것은 selectList 와 selectOne 이다.

- selectList : row가 여러 개일때, 하나하나의 정보를 list에 담기 

- selectOne : 1개의 row를 가져올 때 사용

 

- selectList는 3가지가 있는데, 위의 2가지를 많이 쓴다. 문자열, object 전달하기!

- SELECT에 인자를 전달하는 것을 생각하기. 특정 조건에 맞는 것만 SELECT하려면 값을 가져가야 한다.

- 가져갈 값이 있다면 두번째 인자로 object타입으로 전달하면 된다. object타입이므로 문자,숫자,dto 뭐든지 가능!

 

 

session.selectList( xx, yy ) 일 경우

xx : namespace 부분. 여러개의 mapper 중에 필요한 mapper 찾아가기

yy : id 부분. 여러개의 sql문 중 원하는 sql문 찾아가기

 

- 그리고 SELECT된 row를 어디에, 어떤 타입으로 담을지 결정하는 것이 resultType이다.

.- SELECT문의 칼럼명과 dto의 필드명이 일치해야 한다.

 

 

- Mybatis를 배운다는 것은 이 session을 어떻게 사용하는지를 익히는 것이다.

 

- sqlSession을 배운다는 것은 즉 MyBatis를 배운다는 것이다.

 (ModelAndView는 spring 프레임워크를 배우는 것)

 

- mybatis는 라이브러리이다.

 

 

- select문(spl문)은 memberMapper 안에 작성한다.

- 위와 같이 작성하는데, mybatis가 설치되어 있으면 resultType 부분을 쉽게 작성할 수 있다.

 

 

- MemberMapper와 getList() 메소드 사이의 연결고리들을 잘 보기!!

 

- selectList() 이기 때문에 담는 타입이 List 타입이 되는 것이다.

- resultType이 List<>의 제너릭타입에 영향을 미친다. MemberDto 타입이기 때문에 List<MemberDto>로!

 

* mapper's namespace => member
* sql's id => getList
* resultType => MemberDto
* return Type => List

각각 이렇게 연결할 수 있다.(변수명은 일치시키기만 하면 마음대로 지을 수 있다.)

 

- 이렇게 쓰려면 테이블의 칼럼명과 dto의 필드명이 반드시 일치해야 한다!

 (그러면 mybatis가 알아서 해준다)

 

 

- 예전 dao에 비하면 코딩양이 크게 줄었다.

- resultType으로 설정한 것이 new MemberDto (객체생성까지 한 것) 가 된다.

- 리스트 객체 생성, 반복문 돌기, try~catch 문 작성 등의 내용을 mybatis가 다 해주는 것이다.

 


 

- 이제 member/list 요청을 처리할 컨트롤러가 필요하다!

MemberController.java

package com.sy.spring02.member.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.sy.spring02.member.dao.MemberDao;
import com.sy.spring02.member.dto.MemberDto;

@Controller
public class MemberController {
	
	//필요한 핵심 의존 객체를 주입받는다.
	@Autowired
	private MemberDao dao;
	
	@RequestMapping("/member/list")
	public ModelAndView getList(ModelAndView mView) {
		//주입받은 MemberDao 객체를 이용해서 회원목록을 얻어온다.
		List<MemberDto> list=dao.getList();
		
		//View page에 전달할 Model을 담는다.
		mView.addObject("list", list);
		//View page 정보도 담아서
		mView.setViewName("member/list");
		
		//리턴해준다.
		return mView;
	}
}

 

- 핵심의존객체(MemberDao)를 주입받아서 회원목록을 ModelAndView로 얻어온다.

- 어노테이션이 중요하다! 적절한 어노테이션을 넣어주지않으면 컨트롤러 역할을 하지 못한다.

 @Controller / @Autowired / @RequestMapping

 

 

/member/ list.jsp 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/views/member/list.jsp</title>
</head>
<body>
	<div class="container">
		<h1>회원 목록입니다.</h1>
		<table>
			<thead>
				<tr>
					<th>번호</th>
					<th>이름</th>
					<th>주소</th>
				</tr>
			</thead>
			<tbody>
				<c:forEach var="tmp" items="${list }">
					<tr>
						<td>${tmp.num }</td>
						<td>${tmp.name }</td>
						<td>${tmp.addr }</td>
					</tr>
				</c:forEach>
			</tbody>
		</table>
	</div>
</body>
</html>

 

- 최종적으로는 위와 같이 DB에서 불러올 수 있다.

 

 

- 이 요청을 받기위해 코딩한 페이지들!

 

- Controller

- dao (인터페이스, 클래스)

- sql문을 mapper에서 작성

- list 데이터를 출력할 뷰 페이지

(이후에는 service도 사이에 추가된다.)

 

- list (최종. 브라우저에 나타나는 페이지) ← Controller ← Mapper + MemberDao ← Session에서 객체생성해서 주입

 

 


 

참고) JDBC로 오라클DB의 데이터를 받아오려면 서버의 context.xml에 아래와 같은 설정이 있어야 한다.

<Resource name="jdbc/myoracle" auth="Container"
           type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
           url="jdbc:oracle:thin:@127.0.0.1:1521:xe"
           username="scott" password="tiger" maxTotal="20" maxIdle="10"
           maxWaitMillis="-1"/>

 

- 이 정보가 context.xml에 들어있으면 tomcat이 접속해서 connection 을 가지고 있는다. 직접 관리한다.

- 필요할때 불러와서 사용하면 된다.

 

 

- 기본 Servers 세팅의 context.xml 파일에 넣어주면 된다.

 

- 접속할 컴퓨터의 위치: 127.0.0.1

- username="scott" password="tiger" 으로 오라클에 로그인한다는 뜻!

 

- 접속하는 이름은 마음대로 지을 수 있지만 context.xml 와 Servlet-context.xml에 작성된 이름이 동일해야 한다.