Entity
BroadCast.java
package kr.smhrd.entity;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class BroadCast {
// table에 존재하는 컬럼을 전부 필드로 만들기
private int brdcst_num;
private String brdcst_de;
private String program_nm;
private float nyo_rt;
private float n10s_rt;
private float n20s_rt;
private float n30s_rt;
private float n40s_rt;
private float n50s_rt;
private float n60s_above_rt;
private float male_rt;
private float female_rt;
private float wtchng_rt;
private String fixing_cast_nm;
private String cast_nm;
}
CastCount.java
package kr.smhrd.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CastCount {
// 이름 - 횟수 나만의 자료형
private String name;
private int count;
}
SearchCriteria.java
package kr.smhrd.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SearchCriteria {
// Croteroa => 기준을 정해주는 자료형
// --> 단순한 필드만 존재하기보다는 알고리즘 메소드를 가지고 있음!
// --> PageCriteria -> 페이징기법
// 검색 기준을 잡아주는 자료형
private String type;
private String content;
}
BroadCastController
package kr.smhrd.controller;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import kr.smhrd.entity.BroadCast;
import kr.smhrd.entity.SearchCriteria;
import kr.smhrd.mapper.BroadCastMapper;
@Controller // 1) 클래스파일이 Controller (POJO)임을 알려주기
public class BroadCastController {
// -> 동기통신 요청만 처리하는 controller
// Mapper 인터페이스를 사용할 수 있게끔 연결
@Autowired
private BroadCastMapper mapper;
@GetMapping("/") // 2) url mapping을 "/"로 들어왔을 때 잡아주기
public String index(SearchCriteria cri , Model model) {
System.out.println("기준 >> "+cri);
BroadCast list = mapper.select(cri);
// 서로 다른 클래스 파일 간에 값을 주고받을 수 있는 방법
// --> 메소드의 매개변수
// --> 메소드의 리턴
model.addAttribute("list", list);
return "index"; // 3) "/"로 들어왔을 때 index.jsp 페이지를 forward 방식으로 되돌려주기
}
}
BroadCastRESTController
package kr.smhrd.controller;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import kr.smhrd.entity.BroadCast;
import kr.smhrd.entity.CastCount;
import kr.smhrd.entity.SearchCriteria;
import kr.smhrd.mapper.BroadCastMapper;
@RestController // @Controller + @ResponseBody
public class BroadCastRESTController {
// -> 비동기통신 요청을 처리해주는 Controller
// -> 웹페이지 화면에 데이터를 돌려주는 역할
// -> 메소드를 선언할 때 @ResponseBody 생략이 가능
@Autowired
private BroadCastMapper mapper;
// 월별 데이터 조회할 수 있는 url
@RequestMapping("/getMonthData")
public ArrayList<BroadCast> getMonthData(String program_nm) {
System.out.println("요청이 들어오닝");
ArrayList<BroadCast> result = mapper.getMonthData(program_nm);
return result;
}
// 연령대별 데이터 조회
@RequestMapping("/getSData")
public BroadCast getSData(String program_nm) {
System.out.println("요청");
BroadCast result = mapper.getSData(program_nm);
return result;
}
// 출연진 Top5 조회
@RequestMapping("/getCastCount")
public ArrayList<CastCount> getCastCount(String program_nm) {
// 1. DB에서 데이터 조회
ArrayList<BroadCast> result = mapper.getCastCount(program_nm);
// 2. 조회한 결과값 화면에 출력될 수 있는 형태로 변환
// 1개의 column안에 여러 명의 이름이 들어있음
// 연예인 이름을 전부 담을 수 있는 ArrayList<String>
ArrayList<String> cast_nm = new ArrayList<String>();
for (BroadCast b : result) {
// 2-1) result안에 들어있는 MC이름을 가져와서 ','를 기준으로 쪼개기
String[] temp1 = b.getFixing_cast_nm().split(",");
// 2-2) result안에 들어있는 cast_nm을 가져와서 ,를 기준으로 쪼개기
String[] temp2 = b.getCast_nm().split(",");
// 2-3) 쪼갠 데이터들을 하나의 공간에 보관하기
for (String s : temp1) {
cast_nm.add(s);
}
for (String s : temp2) {
cast_nm.add(s);
}
}
System.out.println(cast_nm);
// 2-4) 전체 연예인 명단에서 중복을 제거
// Collection => 객체 자료구조들 (ArrayList, List, HashMap ...)
// HashSet => 중복값을 허용하지 않는 자료구조 => 데이터를 꺼내려면 iterator 사용해야함
// LinkedHashSet => 순서가 있는 중복값을 허용하지 않는 자료구조
LinkedHashSet<String> castingHashSet = new LinkedHashSet<String>(cast_nm);
System.out.println("중복제거한 결과값 >> "+castingHashSet);
// 2-5) 최종적으로 리턴해줄 자료형
// CastCount => 이름 : 횟수
ArrayList<CastCount> resultList = new ArrayList<CastCount>();
for(String c:castingHashSet) {
if(!c.equals("")) {
// 2-6) 연예인 이름 당 몇 번 등장했는지 횟수를 카운트
// Collections.frequency(객체를 담고있는 컬렉션, 개수를 세고 싶은 객체)
int count = Collections.frequency(cast_nm, c);
// 2-7) 결과값은 resultList에 담아주기
resultList.add(new CastCount(c, count));
}
}
// 2-8) resultList
// => 객체를 정렬 => count 기준으로 정렬
// 객체를 정렬하는 방법
// (1) 정렬하고 싶은 객체가 Comparable 인터페이스를 상속
// (2) Comparator라는 인터페이스를 구현 ★사용★
// 익명함수 방법 1.
// Collections.sort(resultList, new Comparator<CastCount>() {
//
// // compare => 비교하는 함수
// @Override
// public int compare(CastCount o1, CastCount o2) {
// return o2.getCount() - o1.getCount();
// // 양수 => 내림차순 정렬
// // 음수 => 오름차순 정렬
// }
// });
// 익명함수 방법 2. 람다식 표현
// => 익명함수를 호출할 때 많이 사용하는 방식(한줄로 간단히 표현할 수 있는 경우만 사용가능)
// 사용법 : (매개변수) -> 리턴해줘야하는 결과값
Collections.sort(resultList, (o1, o2)->o2.getCount()-o1.getCount());
System.out.println("최종결과 >> "+ resultList);
return resultList;
}
}
BroadCastMapper.java => DAO
package kr.smhrd.mapper;
import java.util.ArrayList;
import org.apache.ibatis.annotations.Select;
import kr.smhrd.entity.BroadCast;
import kr.smhrd.entity.SearchCriteria;
// @Mapper => 버전 업그레이드로 생략 가능
public interface BroadCastMapper {
// 남, 여, 전체 시청률 평균을 조회하는 기능
// 조회한 결과 행이 하나이기 때문에 BroadCast로 받아오기
// session.selectOne();
public BroadCast select(SearchCriteria cri);
// 월별 데이터 조회
public ArrayList<BroadCast> getMonthData(String program_nm);
// 연령대별 데이터 조회
public BroadCast getSData(String program_nm);
// 출연진 TOP5 조회
@Select("SELECT FIXING_CAST_NM, CAST_NM FROM BROADCAST WHERE PROGRAM_NM = #{program_nm}")
public ArrayList<BroadCast> getCastCount(String program_nm);
}
BroadCastMapper.xml => mybatis
<?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="kr.smhrd.mapper.BroadCastMapper">
<select id="select"
parameterType="kr.smhrd.entity.SearchCriteria"
resultType="kr.smhrd.entity.BroadCast">
select PROGRAM_NM,
round(avg(MALE_RT), 3) as MALE_RT,
round(avg(FEMALE_RT), 3) AS FEMALE_RT,
round(avg(WTCHNG_RT), 3) AS WTCHNG_RT
from COM.BROADCAST
<include refid="searchOption" />
GROUP BY PROGRAM_NM
</select>
<!-- 동적 쿼리문 -->
<!-- 매개변수 : SearchCriteria(type, content) type이 프로그램명인지, MC이름인지, null인지
SQL구문이 동적으로 변경 -->
<sql id="searchOption">
<if test="type == null">
WHERE PROGRAM_NM = '뮤직뱅크'
</if>
<if test="type == '방송제목'">
WHERE PROGRAM_NM LIKE CONCAT('%', #{content}, '%')
</if>
<if test="type == 'MC이름'">
WHERE FIXING_CAST_NM LIKE CONCAT('%', #{content}, '%')
</if>
</sql>
<!-- DB에서 조회해 온 결과값의 column과 객체의 필드명이 서로 달랐을 때 사용할 수 있는 resultMap -->
<!-- id : resultMap의 이름(변수명) 정하는 attribute type : 내가 표현하고 싶은 객체(자료형) -->
<resultMap type="kr.smhrd.entity.BroadCast" id="monthData">
<!-- column : 조회해온 column 명칭 / property : 객체의 필드명 -->
<result column="DE" property="brdcst_de" />
<result column="RT" property="wtchng_rt" />
</resultMap>
<!-- 월별 전체시청률 평균 조회 -->
<select id="getMonthData" resultMap="monthData">
SELECT MONTH(BRDCST_DE) AS DE,
round(avg(WTCHNG_RT), 3) AS RT
FROM BROADCAST
WHERE PROGRAM_NM = #{program_nm}
GROUP BY DE
</select>
<!-- 10 ~ 60대 평균시청률 조회 -->
<resultMap type="kr.smhrd.entity.BroadCast" id="sData">
<result column="10대" property="n10s_rt" />
<result column="20대" property="n20s_rt" />
<result column="30대" property="n30s_rt" />
<result column="40대" property="n40s_rt" />
<result column="50대" property="n50s_rt" />
<result column="60대" property="n60s_above_rt" />
</resultMap>
<select id="getSData" resultMap="sData">
SELECT round(avg(N10S_RT), 3) AS
10대
, round(avg(N20S_RT), 3) AS 20대
, round(avg(N30S_RT), 3) AS 30대
, round(avg(N40S_RT), 3) AS 40대
, round(avg(N50S_RT), 3) AS 50대
, round(avg(N60S_ABOVE_RT), 3) AS 60대
FROM BROADCAST
WHERE PROGRAM_NM = #{program_nm}
</select>
</mapper>
자바스크립트 코드가 해석되는 순서
`\${EL}` 로 표현하면 .java에서 스킵하고 .html에서 해석이 되기 때문에
대개 html코드를 ajax로 추가할 때 쓰는 방식(백틱+역슬래쉬+EL식)
index.jsp
일부분임.
<!-- Topbar Search -->
<form action="${cpath}/"
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<select name="type" class="form-control bg-light border-0">
<option value="방송제목">방송제목</option>
<option value="MC이름">MC이름</option>
</select>
   
<input name="content" type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="submit">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Page level custom scripts -->
<script>
// 분리된 js 파일에서 java의 변수를 사용하고 싶다면
// js 파일이 로드되기 전에 script 태그를 열어서 변수를 하나 선언하면 된다.
var program_nm = '${list.program_nm}';
</script>
<script src="resources/js/demo/chart-area-demo.js"></script>
<script src="resources/js/demo/chart-pie-demo.js"></script>
<script >
// 프로그램명이니까 프로그램명을 어디서 받아올 수 있지?
// --> list에서 꺼내올 수 있군!
// list --> java, javascript, html ,css 중에서 java에 있구나
// 현재 내가 코드를 작성하고 있는 파일의 확장자가 뭐지? --> .jsp --> java server page
// 오! 다행이다! java 변수에 접근할 수 있겠다!
// 1) ★EL★
// 2) 표현식 => 꺽새%
// ${EL} => js 변수가 있는지 찾는 경우라서 이렇게 표현하면 안됨!
// '${EL}'처럼 따옴표가 존재해야함!!
// `\${EL}` => .java에서 건너뛰고 .html에서 해석됨.
var program_nm = '${list.program_nm}';
$(function(){
$.ajax({
url : 'getCastCount', // 전송방식? get방식 => 쿼리스트링 문법 ?key=value
data : {
program_nm : program_nm
},
dataType : 'json',
success : function(res){
console.log(res);
console.log(res[0].name);
console.log(program_nm); // 내가 데이터를 가져왔으면 잘 가져왔는지 꼭 출력하기!!
// DOM -> Document Object Model
// 1. id값이 top5인 태그를 가져오기
// document.getElementByID('top5')
// == document.querySelector('#top5')
// == $('#top5')
// jquery, 순수js => 요소(태그)를 조작하는 메소드들 공부!!
// 2. 태그에 추가하기
for(let i = 0; i<5; i++){
$('#top5').append(
`<h4 class="small font-weight-bold">
\${res[i].name} <span class="float-right">\${res[i].count}번</span>
</h4>
<div class="progress mb-4">
<div class="progress-bar bg-danger" role="progressbar" style="width: \${res[i].count}%"
aria-valuenow="\${res[i].count}" aria-valuemin="0" aria-valuemax="100"></div>
</div>`)
}
},
error : function(){
console.log('실패!');
}
})
})
</script>
chart-area-demo.js
ajax 부분만 가져옴.
// VS코드에서 수정 후에 반드시 ctrl+s 저장하기!!
// eclipse로 돌아가서 해당하는 파일을 다시 한 번 열어주기! => 반영이 빨라짐.
// 링크 클릭, 버튼 클릭, 페이지 변환이 일어나면서 데이터 응답 => 동기통신
// 비동기통신 방식으로 DB에서 데이터를 조회해와서 차트를 그리기!
// => $.ajax()
// 문법
// var program_nm = "<c:out value='${list.program_nm}'/>";
$(function () {
$.ajax({
// 1) 어디로 요청을 보내야하는지
url: 'getMonthData',
// 2) 보내줄 값이 있는지
data : {
program_nm : program_nm
},
// 3) 받아올 결과값의 자료형 지정
dataType: 'json',
// 4) 성공했을 때 실행할 함수
success: function (res) {
console.log(res);
// res => 배열 => 객체들이 존재
// res의 0번 인덱스에 있는 객체안에 wtchng_rt를 console에 출력하기
console.log(res[0].wtchng_rt);
console.log(program_nm);
// 1. labels에 들어갈 수 있는 배열을 하나 생성
let monthData = [];
// 3. data에 들어갈 수 있는 배열을 하나 생성
let wtchngData = []
for (let i = 0; i < res.length; i++) {
// 2. 배열에 res 안에 들어있는 brdcst_de라는 데이터를 하나씩 추가
monthData.push(res[i].brdcst_de);
// 4. 배열에 res 안에 들어있는 wtchng_rt라는 데이터를 하나씩 추가
wtchngData.push(res[i].wtchng_rt);
}
// 5. 차트 그리는 전체 코드를 함수로 만들고, 함수를 사용해서 배열 2개를 매개변수로 넘기기
makeAreaChart(monthData, wtchngData);
},
// 5) 실패했을 때 실행할 함수
error: function () {
console.log('실패!');
}
})
})
chart-pie-demo.js
ajax 부분만 가져옴.
// 페이지가 로드 완료되면 비동기통신 시작하도록 코드 작성
// var program_nm = "<c:out value='${list.program_nm}'/>";
$(function(){ // document.ready() => jquery로 표현한 것
$.ajax({
url : 'getSData',
data : {
program_nm : program_nm
},
dataType : 'json',
success: function(res){
console.log(res);
let age = ['10대', '20대', '30대', '40대', '50대', '60대 이상']
// json으로 변환 시 필드는 무조건 소문자로 변경됨!
// 따라서 대문자말고 소문자로 작성 기억!!
let ageData = [res.n10s_rt, res.n20s_rt, res.n30s_rt, res.n40s_rt, res.n50s_rt, res.n60s_above_rt];
console.log(res.n10s_rt);
// 함수선언할 때 매개변수의 순서는 무조건 맞춰야함!
makePieChart(age, ageData);
},
error: function () {
console.log('실패!');
}
})
});
'프레임워크(Framework) > Spring' 카테고리의 다른 글
[Spring] 회원가입할 때 아이디 중복 체크 (0) | 2023.07.16 |
---|---|
name값은 동일한데 value가 여러 개 들어가있을 경우 (1) | 2023.06.14 |
알고리즘_Java 로직 + ajax 비동기통신 (0) | 2023.06.12 |
DB에 저장된 데이터값을 ajax로 그래프 그리기 (1) | 2023.06.08 |
DB에 저장된 데이터 불러오기 (0) | 2023.06.08 |
댓글