D+51::스프링부트+ajax_학생관리페이지만들기(학생상세보기/점수등록 input태그변경/확인버튼으로 변경)/OUTTER JOIN/ANSI JOIN//innerText VS innerHTML차이점

Am.Vinch·2022년 9월 6일
0

20220906_tue

실습내용

  • 학급 및 학생 조회 화면에서 학생이름을 클릭 시, 우측화면에서 학번,학생이름,학급명,국어점수,영어점수,수학점수가 조회되는 테이블을 만들자
  • 우선 해당학생 상세정보조회 쿼리문을 만들어야한다.
  • DB에서 먼저 쿼리가 실행되는지 만들어 본다.

  • DB(파일명: AJAX_실습)
    • 해당 학생(학번 1인 ) 상세정보조회
      -> SCORE_INFO 테이블에 임의값 입력
INSERT INTO SCORE_INFO VALUES (1, 90,80,70, 1);
INSERT INTO SCORE_INFO VALUES (2, 89,87,70, 2);
INSERT INTO SCORE_INFO VALUES (3, 56,80,70, 3);
INSERT INTO SCORE_INFO VALUES (4, 79,85,70, 4);
INSERT INTO SCORE_INFO VALUES (5, 45,50,70, 5);
  • 특정 학번을 가진 학생 정보 상세 조회
SELECT SC.STU_NUM
		, STU_NAME
		, CLASS_NAME
		, KOR_SCORE
		, ENG_SCORE
		, MATH_SCORE
FROM STUDENT_INFO STU , SCORE_INFO SC , CLASS_INFO C
WHERE SC.STU_NUM = STU.STU_NUM
AND STU.CLASS_CODE = C.CLASS_CODE
AND SC.STU_NUM = 10;
  • 위의 쿼리 문제점 발생
    : 문제점) 학생정보테이블에서는 10번 학생이 있지만,
    점수정보테이블에는 5번까지의 학생들만 점수가 있어서
    10번 학생은 상세조회가 완전 안된다
  • 점수가 없어도 학생정보(있는 정보)는 조회하도록 쿼리를 만들어보자.
  • 우선, 위의 쿼리를 간략히 수정해보자
    : 학급명 조회하지않고, 전체 학생조회한다
SELECT SC.STU_NUM
		, STU_NAME
		, KOR_SCORE
		, ENG_SCORE
		, MATH_SCORE
FROM STUDENT_INFO STU , SCORE_INFO SC 
WHERE SC.STU_NUM = STU.STU_NUM;
  • <조회결과>
  • 문제점)실행히 학생 수 만큼 데이터가 15개 나오는 것이 아니라 점수정보테이블 데이터 5개만큼만 조회된다

OUTER JOIN

(참고)INNER JOIN (이전 조인방법))

  • 해결방법)
    : 학생 수만큼 15개가 나오도록 만들어보자
  • OUTER JOIN
  • 점수정보테이블(+)를 조건절에 넣어주면 점수는 나오지않더라도 학생수만큼 나오도록 만들수있다
    cf) 오라클 문법 : (+)
  • NULL값인 점수는 0을 디폴트로 넣어주고싶으면, NVL(컬럼명,0)함수 사용한다
SELECT SC.STU_NUM
		, STU_NAME
		, NVL(KOR_SCORE,0) KOR_SCORE 
		, NVL(ENG_SCORE,0) ENG_SCORE 
		, NVL(MATH_SCORE,0) MATH_SCORE 
FROM STUDENT_INFO STU , SCORE_INFO SC 
WHERE STU.STU_NUM = SC.STU_NUM(+);  

ANSI JOIN

:(디비 종류(오라클..)와 상관없이 모든 디비에서 사용가능한 조인 문법)
-- SELECT,UPDATE,DELETE, INSERT..
-- 1) FROM절에서 , 사용 하지않고 INNER JOIN
-- 2) WHERE절에서 WHERE이 아닌 ON 사용.

SELECT SC.STU_NUM
		, STU_NAME
		, KOR_SCORE 
		, ENG_SCORE 
		, MATH_SCORE 
FROM STUDENT_INFO STU INNER JOIN SCORE_INFO SC 
ON STU.STU_NUM =  SC.STU_NUM -- 조인조건을 위해 필요한 조건절 ON//5개 데이터 조회()
WHERE STU.STU_NUM =  1;-- 추가적인 조건을 주기위한 조건절// 1개의 해당학생만 조건조회 

- LEFT OUTER JOIN

  • 왼쪽 학생테이블(15개 데이터)기준 아웃터 조인,부족한 데이터는 NULL값
SELECT SC.STU_NUM
		, STU_NAME
		, KOR_SCORE 
		, ENG_SCORE 
		, MATH_SCORE 
FROM STUDENT_INFO STU LEFT OUTER JOIN SCORE_INFO SC 
ON STU.STU_NUM =  SC.STU_NUM; 

  • 다시 본론으로 학급명도 넣어서 해보자
    -- 학번 1은 조회되지만 10은 조회 안된다
    --하지만 점수정보가 없는 학생이더라도 학급명과 함께 점수정보도 조회해보자
    -- OUTER JOIN , NVL 사용
SELECT STU.STU_NUM
		, STU_NAME
		, CLASS_NAME
		, NVL(KOR_SCORE,0) KOR_SCORE
		, NVL(ENG_SCORE,0) ENG_SCORE
		, NVL(MATH_SCORE,0) MATH_SCORE
FROM STUDENT_INFO STU ,  CLASS_INFO C ,SCORE_INFO SC 
WHERE STU.CLASS_CODE = C.CLASS_CODE
AND STU.STU_NUM =SC.STU_NUM(+)
AND STU.STU_NUM = 10;

실습내용

  • 해당학생 상세정보 조회
  • 위 쿼리문 이용해서 학생상세조회 테이블을 띄우고 밑에 '점수등록' 버튼 생성
  • 점수등록 버튼 클릭하면 국어,영어,수학 점수를 입력할 수 있도록 점수 영역을 INPUT 태그로 바꾼다.
  • 단,INPUT 태그에는 기존의 점수는 그대로 유지가 되어야한다.
  • 점수등록이라는 버튼이 '확인'이라는 버튼으로 바뀌어야한다.(여기까지 진도)

(내일 실습 확인)

  • 확인 버튼 클릭 시, 점수 정보가 등록 되어야 한다.
  • 점수등록(수정)이 완료되면 ALERT으로 '점수변경 성공!'띄운다!

이름을 클릭했을 시, 해당학생 상세정보 조회
:function showDetail(stuNum)

  • 테이블 그리기 전에, 먼저 컨트롤러가서 필요한 데이터 가져와야한다. 매개변수 stuNum 이 넘어와서 학생번호 데이터를 받아와야한다.
  • ajax사용 이유? 디비작업 조회해야하는데 이전 목록조회한 곳에서 데이터를 가져와서 상세정보 조회를 하는데 별도로 페이지이동 필요없어서!
  • 요청경로:컨트롤러 경로url: '/stu/getDetailInfo'
  • stu_manage.js
function showDetail(stuNum) {//매개변수 학생번호 데이터 받아오기
		$.ajax({
		url: '/stu/getDetailInfo',
		type: 'post',
		data: {'stuNum':stuNum}, 
		//컨트롤러가 실행하면 ajax실행으로 success구문 실행된다.
		success: function(result) {//리턴값으로 받는 결과 result(상세조회 쿼리결과값)
			let str='';

			/*html에서 나타날 코드 여기 작성 */
				str += '<table class = "stuDetailTable">';
				str += '<tr>';
				str += '<td>학생번호</td>';
				str += '<td>학생이름</td>';
				str += '<td>소속 학급명</td>';
				str += '</tr>';
				str += '<tr>';
				str += `<td>${result.stuNum}</td>`;
				str += `<td>${result.stuName}</td>`;
				str += `<td>${result.className}</td>`;
				str += '</tr>';
				str += '<tr>';
				str += '<td>국어점수</td>';
				str += '<td>영어점수</td>';
				str += '<td>수학점수</td>';
				str += '</tr>';

				/* 점수 데이터 가져오는 이 영역을 input 태그로 바꾸기 */
				str += '<tr id="scoreTr">';
				str += `<td>${result.korScore}</td>`;
				str += `<td>${result.engScore}</td>`;
				str += `<td>${result.mathScore}</td>`;
				str += '</tr>';
				
				str += '</table>';
				//점수 등록 버튼 생성: 점수등록 클릭시, input태그로 변경
				str += '<div style="text-align=center; margin-top:15px;">';
				str += '<input type="button" value="점수등록">';
				str += '</div>';
			const detailTd = document.querySelector('#detailTd');
			
			//빈값으로 바꾸고 붙이기를 반복한다
			//innerHTML : 선택한 태그에 빈문자를 주면 선택태그 안의 내용(innerHTML) 모두 삭제
			detailTd.innerHTML= '';
			//insertAdjacentHTML('(위치)', 넣을 문자) : 뒤에 문자열을 어느 위치에 넣을지  	
			detailTd.insertAdjacentHTML('beforeend',str);
			},
		
		error: function() {
			alert('실패');
		}
	});

}
  • stuController
    : 학생상세조회
	@ResponseBody
	@PostMapping("/getDetailInfo")
	public StuVO getDetailInfo(int stuNum) {
		//상세조회(컨트롤러 ->(ajax) js의 success 실행)
		return stuService.getDetailStu(stuNum);//쿼리실행 결과 데이터 던져주기
	}
  • stu_manage.html
  • 이름을 클릭하면 상세정보 메소드로 이동
  • (td태그 - span태그 차이점)
    : 학생이름뿐만 아니라, 옆 공백을 클릭했을 때도 이동하는 td태그와는 달리, span태그안에 속성넣으면 컴팩트하게 글자만 클릭했을 때, 상세조회 된다!
    <td th:text="${stuInfo.stuName}"></td>
  • 타임리프 온클릭으로 데이터 보내는 방법
    타임리프 온틀릭(th:onclick)을 사용해야 안에있는 문자가 변수로 인식한다!
  • 학생이름클릭하면 학생번호 데이터를 가져가야하기때문에 상세보기 메소드(js)이동시, 메소드가 필요로하는 매개변수 학생번호를 가져가야한다.
    <span th:text="${stuInfo.stuName}" th:onclick="showDetail([[${stuInfo.stuNum}]]);"></span></td>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">

.layoutTable{
	width: 1000px;
	margin: 0 auto;
	border: 1px solid black;
	border-collapse: collapse;
	margin-top: 40px;
	text-align: center;
	
}
.layoutTable > tbody >tr, .layoutTable > tbody > tr >td{
	border: 1px solid black;
}
.layoutTable > tbody> tr{/* 자식 */
	height: 500px;
}
.layoutTable > tbody> tr > td{/* 자식 */
	vertical-align: top;
	padding: 20px;
}
.stuListTable, .stuDetailTable{
	width: 400px;
	border: 1px solid gray;
	border-collapse: collapse;
	margin: 0 auto;
	text-align: center;
}
.stuListTable tr,.stuListTable td{/* 자손 */
	border: 1px solid gray;
}
.stuDetailTable tr,.stuDetailTable td{/* 자손 */
	border: 1px solid gray;
}
span:hover {
	cursor: pointer;/* 손가락모양으로 커서변경 */
}
</style>
</head>

<body>

<table class="layoutTable">
	<colgroup>
			<col width="50%">
			<col width="50%">
	</colgroup>
	<tr>
		<td>
			<div style="margin-bottom: 10px;" align="center">
				<!-- onchange : select 값이 바뀔 때마다 "" 실행 -->
				<select onchange="changeClass()">
					<option value="0">전체</option>
					<option th:each="classInfo : ${classList}" th:text="${classInfo.className}" th:value="${classInfo.classCode}"></option>
				</select>
			</div>
		
		<div>
		<!-- 화면이 뜨자마자 이 테이블은 없다. 이름을 클릭해야만 화면에 보인다 -->
			<table class="stuListTable">
				<thead>
					<tr>
						<td>학번</td>				
						<td>이름</td>				
						<td>나이</td>				
						<td>학급명</td>				
					</tr>
				</thead>
				
				<tbody>
					<th:block th:each="stuInfo : ${stuList}" >
						<tr>
							<td th:text="${stuInfo.stuNum}" th:value="${stuInfo.stuNum}" ></td>				
							
							<!-- 이름을 클릭하면 상세정보 메소드로 이동 -->
							<!-- td태그 안에 말고 span태그안에 속성넣으면 글자만 클릭해야 상세조회 된다!(차이점) -->
							<!-- <td th:text="${stuInfo.stuName}"></td> -->
							
							<!-- 타임리프 온클릭으로 데이터 보내는 방법 -->
							<td><!-- 타임리프 온틀릭(th:onclick)을 사용해야 안에있는 문자가 변수로 인식한다! -->
								<!-- 학생이름클릭하면 학생번호 데이터를 가져가야하기때문에!! -->
								<span th:text="${stuInfo.stuName}" 
								th:onclick="showDetail([[${stuInfo.stuNum}]]);"></span>
							</td>
																						
							<td th:text="${stuInfo.stuAge}" ></td>				
							<td th:text="${stuInfo.ClassName}" ></td>				
						</tr>
					</th:block>
				</tbody>
				
			</table>
		</div>
		</td>
		<!-- 우측화면 상세정보 테이블 js에서 메소드 실행-->
			<td id="detailTd">
				<!--상세정보 테이블 들어가는 곳 -->	
			</td>
		</tr>
</table>

<!-- jquery 문법 로딩 -->
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<!-- 자바스크립트 파일과연결 -->
<script type="text/javascript" th:src="@{/stu_manage.js}"></script>
</body>
</html>

  • stu_manage.js
    : 처음 그려질때는 html 으로 테이블내용이 그려지지만, 이후 부터는 js로 그려진다. 때문에 다시 지워지고 그리는 것이다.
    :그래서 학급 선택 조회하면, 자스에서 changeClass 함수가 실행이되는데 이 함수를 통해 데이터 테이블이 그려진다.
    : 학급변경 조회했을 때에도 (00반) 실패창이 안뜨고 데이터가 조회되려면, 자스에서 만든 str구문에서 showDetail() 상세보기 메소드 안에 반드시 학생번호 데이터를 넘겨줘야한다!!
    str += `<span>${stu.stuName}</span>`;

점수등록 메소드
: function setScore(){}

  • 점수등록 누르면 원래 그린 테이블 지우고 다시 그려줘야한다.(이전 목록조회와 같음)
    :그래서 원래 점수값 데이터 받는 td태그부분들을 지워주고 다시 그려준다.
  • 가장 먼저 태그를 먼저 선택해야한다.(id값부여)
    //선택한 태그의 속성값 데이터 불러오기
    //주의) korScoreTd 안의 글자와 value속성값은 서로 다르다!
    - korScoreTd.vlaue;//korScoreTd의 value 속성값
    - korScoreTd.innerText;//td태그사이 text값 ${result.korScore}

  • 방법1) 공부용_ 반복이 많아서 다른 방법 사용
    //const korScoreTd = document.querySelector('#korScoreTd');
    //korScoreTd.innerText='';//원래 있는 국어점수 내용 지우기(빈값주기)
    //const engScoreTd = document.querySelector('#engScoreTd');
    //engScoreTd.innerText='';//원래 있는 국어점수 내용 지우기(빈값주기)
    //const mathScoreTd = document.querySelector('#mathScoreTd');
    //mathScoreTd.innerText='';//원래 있는 국어점수 내용 지우기(빈값주기)

  • 방법2) tr에 id값 부여하여 태그 선택(반복문 피하기위해)
    //const scoreTr = document.querySelector('#scoreTr');//1개 들고오니까
    const scoreTds = document.querySelectorAll('#scoreTr > td');//여러개 td들고오니까 모두 들고올려면 all
    //scoreTd 에 input태그 넣기
    const str = '<input type="text" style="width:90%;" placeholder="${scoreTd.innerText}">';
    //오류발생_여러데이터있을 때 -> scoreTds.innerText='';
    //여러개 데이터 뽑을 때-> 반복문사용!!!
    for(const scoreTd of scoreTds){scoreTd.innerText='';scoreTd.insertAdjacentHTML("afterbegin",str);//beforeend도 가능}
  • stu_manage.js
function setScore(){
	const btn = document.querySelector('input[type="button"]');
	
	//만약 버튼이 점수등록 일때는 점수 수정 update 실시
	if(btn.vlaue == '점수등록'){//update 수정
		
			const scoreTds = document.querySelectorAll('#scoreTr > td');//여러개 td들고오니까 모두 들고올려면 all
			//오류발생_여러데이터있을 때 -> scoreTds.innerText=''; 
			//여러개 데이터 뽑을 때-> 반복문사용!!!
			for(const scoreTd of scoreTds){
				//1)원래가지고 있는 데이터(점수)를 저장
				const score= scoreTd.innerHTML;//td의 내용은 innerHTML
				//2)내용지우기(빈값)
				scoreTd.innerText= '';
				//3)scoreTd 에 input태그 넣기(``사용, 화면에 보이는 값은 value 속성) 
				const str = `<input type="text" style="width:90%;" value="${score}">`;		
				//4) 원하는 위치에 str 넣기
				scoreTd.insertAdjacentHTML("afterbegin",str);//beforeend도 가능
				
			}	
			
			//점수등록 버튼 '확인'으로 바꾸기
			btn.value ='확인';//눈에 보이는 속성 value	
	}
	//그렇지 않으면('확인'버튼일 때), 점수등록한다(DB작업)_merge into 사용
	else{
		
		
	}	
}

innerText VS innerHTML차이점

innerText VS innerHTML

  • 1. 값 가져오기 (innerText vs innerHTML)
    • element.innerText;
      예시)A
      이 속성은 element 안의 text 값들만을 가져옵니다.
    • element.innerHTML;
      예시)<div>A</div>
      innerText와는 달리 innerHTML은 element 안의 HTML이나 XML을 가져옵니다.

  • 2. 값 설정하기 (innerText vs innerHTML)
    • element.innerText = "<div style='color:red'>A</div>";
      예시) <div style='color:red'>A</div>
      element.innerText에 html을 포함한 문자열을 입력하면, 
      html코드가 문자열 그대로 element안에 포함됩니다.
    • element.innerHTML = "<div style='color:red'>A</div>";
      예시) A
      위와 같이 element.innerHTML 속성에 html코드를 입력하면,
      html element가 element안에 포함되게 됩니다.
      위 예제에서 'innerHTML()'을 클릭하면,
      입력된 html태그가 해석되어 빨간색A 가 나타나는 것을 확인 할 수 있습니다.
      참고>https://hianna.tistory.com/480
profile
Dev.Vinch

0개의 댓글