본문 바로가기

BackEnd/Spring

[실습] DB데이터로 Navigation 만들기 (Mybatias,Gson)

< 사용할 DB 테이블 >

해당 테이블의 데이터들을 가져와서 navigation을 만들어보자.

 

1. jdbc 및 dbcp 의존성 추가하기 

<dependency>
	<groupId>org.mariadb.jdbc</groupId>
    <artifactId>mariadb-java-client</artifactId>
    <version>2.2.1</version>
</dependency>

<dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.4</version>
</dependency>

해당 과제는 maven을 통해서 설치해주었다.

사용할 jdbc 및 dbcp를 설치 해준다.

해당 과제에서는 mariadb jdbc를 설치해주었따.

dbcp는 db에 상관없이 위의 코드를 이용해서 설치해주자.

2. context-datasource에 bean객체 추가해주기

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.mariadb.jdbc.Driver"/>
        <property name="url" value="jdbc:mariadb://localhost:포트번호/스키마명" />
        <property name="username" value="아이디"/>
        <property name="password" value="비밀번호"/>
    </bean>

3. MainController에 do요청 추가하기

	@RequestMapping("/ajaxSelectMenuList.do")
	public void ajaxSelectMenuList (HttpServletRequest request,
	HttpServletResponse response) throws Exception {
		
	}

해당 do 요청에는

전체적인 비즈니스 로직을 담당할 MainService가 있다.

MainService 중에 SQL 매핑을 하는 MainMapper가 있고 MainMapper의 리턴값을 MainService에 리턴한다.

그 값은 HashMap에 value로 넣고 JsonUtil을 통해서 응답할 것이다.

 

이와 같은 로직은 다음과 같이 작성된다.

private MainService mainService;
	public void ajaxSelectMenuList (HttpServletRequest request,
	HttpServletResponse response) throws Exception {
		List<EgovMap> menuList = mainService.selectMenuList();
		
	      HashMap<String, Object> resultMap = new HashMap<String, Object>();

	      resultMap.put("result", "SUCCESS");
	      resultMap.put("list", menuList);

	      response.setCharacterEncoding("utf-8");

	      PrintWriter out = response.getWriter();
	      out.write(JsonUtil.HashMapToJson(resultMap));
		
	}

<MainContorller의 selectMenuList>

@Service("mainService")
public class MainServiceImpl implements MainService {
	
	@Resource(name="mainMapper")
	private MainMapper mainMapper;
	
	@Override
	public List<EgovMap> selectMenuList() throws Exception {
		List<EgovMap> menuList = new ArrayList<EgovMap>();
		try{
			menuList = mainMapper.selectMenuList();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return menuList;
	}

}

< MainService의 구현체 >

MainService는 mainMapper의 결과값을 리턴한다.

 

4. SQL Mapping

@Mapper("mainMapper")
public interface MainMapper {

	List<EgovMap> selectMenuList();

}

< MainMapper의 인터페이스 >

 

MainMapper는 구조체를 가지지 않고 sqlmapper를 이용하여 메소드를 동작한다.

 

이를 위해선 일단 context-mapper의 설정이 필요하다.

 	<bean class="egovframework.rte.psl.dataaccess.mapper.MapperConfigurer">
		<property name="basePackage" value="com.webproject.**.service.impl" />
	</bean>

< context-mapper.xml >

value에 mapper의 위치를 입력한다.

현재 나의 프로젝트에선

com.webproject.main.service.impl 이다.

 

그 다음 mybatias 설정을 해준다.

	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:/com/sqlmap/webproject/sql-mapper-config.xml" />
		<property name="mapperLocations" value="classpath:/com/sqlmap/webproject/mappers/*.xml" /> 
	</bean>

< context-mapper.xml>

첫번째 property 의 ref 는 context.dataSource의 DB와 연결해준다.

두번째 property 의 value는 설정을

세번째 property 의 value는 실제로 mapping할 mybatias 프로젝트를 설정해준다.

 

이후 mybatias 프로젝트를 생성해준다.

<?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.webproject.main.service.impl.MainMapper">
   <select id="selectMenuList" resultType="egovMap">
      SELECT MENU_CoDe, MENU_NaMe, UPPeR_MENU_CoDe, MENU_LeVel,
            MENU_URL, USE_YesorNo, DisPlay_YesorNo, SORT_SEQUENCES
            REGist_ID, REGist_DaTe
      FROM table_MENU
      WHERE USE_YesorNo = 'Y'
        AND DisPlay_YesorNo = 'Y'
      ORDER BY MENU_CoDe
   </select>
</mapper>

< MainMapper.xml >

mapper 태그의 namespace는 Mapper가 있는 클래스를 입력해준다. 

두번째 <select> 태그는 select를 요청할 때 사용되고 id에는 메소드 명, resultType은 리턴타입을 입력해준다.

태그 안의 내용은 실제 쿼리문을 작성해주면된다.

 

마지막으로 리턴타입이 어떤 것인지 알려줘야 한다.

이는 sql configration에서 설정한다.

<configuration>
    <typeAliases>
		<typeAlias alias="egovMap" type="egovframework.rte.psl.dataaccess.util.EgovMap"/>
    </typeAliases>
</configuration>

<sql-mapper-config.xml>

이름은 egovMap이고

그 타입은 해당 타입이라는 것이 입력되어 있다.

 

* 이 때 egovMap이란 Map과 같이 키와 값을 가지는데, 모든 키 값에 _(underScore)를 camelCase형식으로 바꾸어 준다.

public void ajaxSelectMenuList (HttpServletRequest request,
HttpServletResponse response) throws Exception {
  List<EgovMap> menuList = mainService.selectMenuList();
  HashMap<String, Object> resultMap = new HashMap<String, Object>();
System.out.println("결과: "menuList) //결과: [{menuCode=M010000, menuName=큰 메뉴1, menuLe...//

출력하면 다음과 같은 결과를 얻을 수 있다.

 

이 값을 자바스크립트에서 사용하기 위해 Json형식으로 전환해줘야한다.

다양한 방법이 있지만 해당 프로젝트에선 Gson을 이용하였다.

 

5. HashMap to Json

Gson은 구글에서 제공하는 Json to Map 과 Map to Json을 해주는 라이브러리이다.

 

의존성 추가를 해주자.

       <dependency>
         <groupId>com.google.code.gson</groupId>
         <artifactId>gson</artifactId>
         <version>2.5</version>
         <scope>compile</scope>
      </dependency>

<pom.xml>

 

이후에 gson의 toJson값을 리턴하는 메소드와 클래스를 생성하자.

import com.google.gson.Gson;

public class JsonUtil {
	public static String HashMapToJson(HashMap<String, Object> map){
		Gson gson = new Gson();
		return gson.toJson(map);
	}
}

< webproject/*/util/JsonUtil >

private MainService mainService;
	public void ajaxSelectMenuList (HttpServletRequest request,
	HttpServletResponse response) throws Exception {
		List<EgovMap> menuList = mainService.selectMenuList();
		
	      HashMap<String, Object> resultMap = new HashMap<String, Object>();

	      resultMap.put("result", "SUCCESS");
	      resultMap.put("list", menuList);

	      response.setCharacterEncoding("utf-8");

	      PrintWriter out = response.getWriter();
	      out.write(JsonUtil.HashMapToJson(resultMap));
		
	}

< MainController >

해당 값을 리턴하는 것으로 요청에 대한 응답을 받을 수 있다.

 

6. View에서 요청하기

현재 main.do 에서는 페이지만 요청하고 있다.

main.do 에서 페이지 요청과 동시에 데이터도 요청 할 수 있지만, 그것보다

페이지 렌더링과 별개로 데이터를 가져오는 요청을 하기 위해서 ajax를 사용한다.

<script type="text/javascript">
$.ajax({
  url : "ajaxSelectMenuList.do",
  type : "post",
  success : function(data) {
    var jObj = JSON.parse(data);
      if(jObj.result = "SUCCESS"){
        if(jObj.list.length > 0) {
        var htmlStr = "";
          $.each(jObj.list, function(i, list1) {
          if(list1.menuLevel === 1 && 
          list1.menuUrl !== null && 
          list1.menuUrl !== "" && 
            list1.menuUrl !== undefined ){
            htmlStr += "<li class = 'dropdown active'>";
            htmlStr += "<a href=`'"+list1.menuUrl+"'>";
            htmlStr += list1.menuName;
            htmlStr += "</a>";
            htmlStr += "</li>";	
            }else{
              if(list1.menuLevel === 1) {
              htmlStr += "<li class = 'dropdown'>";
              htmlStr += "<a tabindex='0' data-toggle='dropdown' data-submenu='' aria-expanded='false'>";
              htmlStr += list1.menuName;
              htmlStr += "<span class='caret'></span>";
              htmlStr += "</a>";

              htmlStr += "<ul class = 'dropdown-menu'>";
                $.each(jObj.list, function(i, list2){
                  if(list1.menuCode === list2.upperMenuCode && list2.menuLevel === 2) {
                  htmlStr += "<li><a href =`"+list2.menuUrl+"`>";
                  htmlStr += list2.menuName;
                  htmlStr += "</a></li>";
                  }
                });
              htmlStr += "</ul>";
              htmlStr += "</li>";
              }
            }
          });
        $("#navbar-nav").append(htmlStr);
      }
    } 
  }
})
</script>

참고로 response의 값인 data의 로그 값은 다음과 같다.

data는 문자열로 반환된다.

object처럼 사용하기 위해서 JSON.parse메소드를 이용하여 오브젝트와한다.

이후에 result가 성공적이고

값이 있다면 jQuery의 $.each를 이용하여 태그들을 생성한다.

결과는 다음과 같다.