아키텍처와 함께

블로그 이미지
by gregorio
  • Total hit
  • Today hit
  • Yesterday hit

C3는 D3 Chart 기반으로 쉽게 Chart를 생성할 수 있는 Chart 솔루션이다.


C3 Chart는 다양한 Chart를 제공하고 있으며, 개발 시 http://c3js.org/를 참조하여 개발을 수행할 수 있다.


C3 Chart를 사용하면서 데이터를 생성하는데 이슈가 되었던 부분들을 간략하게 설명한다.


■ JSON 데이터 처리

C3 Chart는 Json Data를 사용할 수 있다고 되어 있으나, 예제를 찾을 수 없어 column으로 데이터를 처리하였다.

또한 java script에서 loop를 최소화하기 위해 Oracle의 PIVOT 기능을 이용하여 데이터 조회 시 Row를 Column으로 변환하였다.



■ PIVOT을 이용한 Row를 Column으로 변환


SELECT *

FROM (

     SELECT TO_CHAR(START_TIME, 'YYYY-MM-DD') START_DAY

          ,INTERFACE_ID

     FROM TRANS_LOG

     WHERE 1 = 1

<if test='startDate != "" and startDate != null'>

     <![CDATA[AND START_TIME >=  #{startDate}]]>

    </if>

<if test='interfaceId != "" and interfaceId != null'>

AND   INTERFACE_ID LIKE '%' || #{interfaceId} || '%'

</if>

)

PIVOT 

(

COUNT(START_DAY)

    FOR START_DAY IN

    <foreach collection="condDate" item="item"  open="(" close=")" separator=",">

            ${item}

        </foreach>

)  


PIVOT을 사용할 경우 바인딩 변수를 사용할 수 없으며, 바인딩 변수를 사용하면 ORA-56900 오류가 발생한다.


이를 해결하기 위해서 Mybatis의 #{itme} 대신에 ${item}을 사용하여 해결하였다.


또한 PIVOT의 IN 내에 조건을 바인딩하기 위해 사전에 다음 SQL로 데이터를 조회한 후 조회결과를 파라미터를 전송하였다.


■ PIVOT의 IN 바인딩 데이터 조회

SELECT q'[']' || START_DATE || q'[']' START_DATE

FROM   

   (SELECT DISTINCT(TO_CHAR(START_TIME, 'YYYY-MM-DD')) START_DATE FROM TRANS_LOG

WHERE 1 = 1

<if test='startDate != "" and startDate != null'>

<![CDATA[AND   START_TIME >= #{startDate}]]>

</if>

<if test='interfaceId != "" and interfaceId != null'>

AND   INTERFACE_ID LIKE '%' || #{interfaceId} || '%'

</if>

ORDER BY 1


START_DATE를 값으로 사용하기 위해 조회 시 Single Quotation을 붙여주었다.


 


■ JSP Source

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">


<link rel="stylesheet" href="/resources/css/jquery-ui-1.10.1.css">

<link rel="stylesheet" href="/resources/css/table.css">

<link rel="stylesheet" href="/resources/css/c3.min.css">

<link rel="stylesheet" href="/resources/css/melon.datepicker.css">




<script type="text/javascript" src="/resources/js/jquery-3.3.1.min.js"></script>

<script type="text/javascript" src="/resources/js/jquery-ui-1.10.1.min.js"></script>  

<script type="text/javascript" src="/resources/js/c3.min.js"></script>

<script type="text/javascript" src="/resources/js/d3.v3.min.js" charset="utf-8"></script>


<script>


$(document).ready(function() {

$("#btnSearch").click(function(e) {

    e.preventDefault();

    

debugger;

var objectData =

         {

             startDate: $('#startDate').val(),

             chartType: $('#chartType').val(),

             interfaceId: $('#interfaceId').val()

         };


var sendData = JSON.stringify(objectData);

    $.ajax({

        type: "POST",

        url: '/chart/showStatistics.do',

        data : sendData,

        dataType : "json",  //Cross domain

        contentType: "application/json",

        success : function(response, status, xhr) {

        alert(response);

        debugger;

        console.log(response); 

        showChart(response);

        }, 

        error: function(jqXHR, textStatus, errorThrown) {

        debugger;

        console.log(jqXHR.responseText); 

        }

    });

});


});


//Date Picker

$(function() {

    $( "#startDate" ).datepicker({

    defaultDate: new Date(),

    dateFormat: "yy-mm-dd",

    changeMonth: true, 

        changeYear: true,

        dayNames:['Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat']

    });

});

function showChart(response) {

debugger;

var graphType =  $('#chartType').val().toUpperCase() + " Statistic Graph";

$( "#graphType" ).text(graphType);

var categories=[];

$.each(response.categories, function(idx, data) {

categories.push(data);

});

var columns = [];

$.each(response.columns, function (idx, data) {

var col = [];

var idx = 0;

$.each(data, function(key, value) {

debugger;

col[idx] = value;

idx++;

});

columns.push(col);

});

var chart = c3.generate({

bindto: "#interfacechart",

    size: {

        height: 600,

        width: 1200

    },

    data: {

        type: 'bar',

        columns: columns,

    },

    bar: {

        width: {

            ratio: 0.3 // this makes bar width 50% of length between ticks

        }

        // or

        //width: 100 // this makes bar width 100px

    },

    axis: {

    x: {

    type: 'category',

    categories:categories

    }

    },

    grid: {

        x: {

            show: true

        },

        y: {

            show: true

        }

    }

});


// setTimeout(function () {

// chart.load({

//         columns: [

//             ['data3', 130, -150, 200, 300, -200, 100]

//         ]

//     });

// }, 1000);

}


</script>

<title>Interface Monitoring</title>

</head>


<body>

<!-- Search Area -->

<div class="container">

        <form action="">

        <div class="fieldName">

        <label>START DATE</label>

        </div>

        <div class="select">

            <input type="text" id="startDate" size=10 style="align=center;"/>

        </div>

       

        <div class="fieldName">

            <label>Statistic Period</label>

  </div>

        <div class="select">

            <select name="chartType" id="chartType">

        <option value="daily">Daily</option>

        <option value="monthly">Monthly</option>

    </select>

</div>

        <div class="fieldName">

            <label>Interface Name</label>

  </div>

<div class="data">

<input type="text" id="interfaceId" title="Enter Interface Name" size="30"></input>

</div>

        <div class="logbutton">

            <button  id="btnSearch">Search</button>

        </div>

  </form>

</div>


<div>

<label style="height:100%;padding:5px; margin-top:10px; font-family:Sans-serif; font-size:1.2em;" id="graphType">Statistic Graph</label>

</div>

<div id="interfacechart" style="width: 1200px; height: 500px;"></div>

</body>

  

</body>

</html> 



■Controller 소스


import java.util.HashMap;

import java.util.List;

import java.util.Map;


import javax.annotation.Resource;


import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.servlet.ModelAndView;


import cmn.util.base.BaseController;

import cmn.util.dao.CamelMap;

import sehati.inf.chart.service.ChartService;


@Controller

public class CharController extends BaseController {


@Resource(name = "chartService")

private ChartService chartService;

@RequestMapping("/chart/viewChart")

public ModelAndView viewChart() throws Exception {

ModelAndView mav = new ModelAndView();

mav.setViewName("InterfaceStatistics");

return mav;

}

@RequestMapping(value="/chart/showStatistics.do")

public @ResponseBody Map<String, Object> showStatistics(@RequestBody Map<String, Object> param) throws Exception {


Map<String, Object> resultMap = new HashMap<String, Object>();

/** Search Condition **/

List<String> categories = chartService.selectPivotQueryTarget(param);

param.put("condDate", categories);

List<CamelMap> resultList = chartService.selectChartData(param);


resultMap.put("categories", categories);


resultMap.put("columns", resultList);

return resultMap;

}

}

 


먼저 날짜별 PIVOT을 적용하기 위해 날짜를 조회한 후 실제 데이터 조회하기 위해 condData를 파라미터로 전달한다.


'Spring Framrwork' 카테고리의 다른 글

spring framework interceptor  (0) 2018.03.02
Google Map javascript API 사용법  (0) 2018.02.07
Spring Batch 모니터링 SQL  (0) 2018.02.03
MybatisBatchWriter 오류 해결방법  (0) 2018.02.03
Solve the Cross Domain issue with JSP  (0) 2018.02.02
AND

ARTICLE CATEGORY

분류 전체보기 (56)
Spring Framrwork (33)
Linux (1)
APM (1)
Java (8)
python (0)
ant (1)
chart (1)
OS (1)
tomcat (1)
apache (1)
database (0)

RECENT ARTICLE

RECENT COMMENT

CALENDAR

«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

ARCHIVE

LINK