내용 content, 안쪽여백 padding, 바깥여백 margin, 테두리 border 등으로 구성
브라우저는 박스의 기본 크기와 속성, 위치를 기반으로 화면에 자리잡음
width/height 속성:
요소의 너비와 높이를 지정할 때 사용
단, 콘텐츠 영역보다 콘텐츠가 크면 영역을 넘쳐서 표시됨
사용 가능 단위는 px, %
margin/padding 속성:
콘텐츠를 둘러쌓고 있는 4개 방향( top/right/bottom/left )에 대해 지정가능
margin, padding은 1 갯값, 2 갯값, 3 갯값, 4 갯값을 이용해서 지정할 수 있음
한쪽면, -top, -right, -bottom, -left 속성을 이용해서
세부적으로 margin이나 padding을 조절할 수 있음.
자동 수평 정렬 :
margin의 left/right 속성을 auto라고 선언하면
해당 요소를 브라우저 중앙에 배치할 수 있음
테두리 :
border-style, border-color, border-width 등의 속성을 가짐
padding/margin과 마찬가지로 단축 표기식으로 선언할 수 있음
border : 선두께 선종류 선색깔 형태로 정의해야 함
border-style : dotted, dashed, solid, doubled...
border-width : thin, thick, medium, 수치 값,...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>박스속성</title>
<style>
#box1 { width: 300px; background: yellow; padding: 25px; border: 5px solid navy; margin: 25px;}
#box2 { width: 300px; background: yellow; padding: 25px; border: 5px solid navy; margin: 25px; height: 100px;
overflow: hidden;} /*overflow 넘치는부분을 hidden 숨겨버렸따뤼 ~*/
#box3 { width: 300px; background: yellow; margin: 25px; border: 5px solid navy;
padding: 25px; /* 4개의 방향을 단일값으로 선언 */
padding : 25px 25px; /*2개의 방향(상하/좌우)을 단일값으로*/
padding : 25px 25px 25px; /*3개의 방향(상/좌우/하)을 단일값으로 선언*/
padding : 5px 10px 15px 25px; /*4개의 방향(상/우/하/좌)을 단일값으로 선언*/
padding-top: 5px;
padding-right: 20px;
padding-bottom: 45px;
padding-left: 65px;
}
#box4 { width: 300px; margin: 5px auto;}
#box5 { width: 300px; border : 5px outset red;
border-top-style: dotted;
border-right-style: dashed;
border-left-style: double;
border-bottom-style: solid;
border-style: dotted dashed double solid;
/*점선-더긴점선-두줄 -굵음*/
border-top-color: yellow;
border-right-color: darkorange;
border-bottom-color: orchid;
border-left-color: darkred;
border-color: orange green navy lime;
border-width: thin thin thick thick;
}
</style>
</head>
<body>
<h1>박스모델</h1>
<div id="box1">There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.</div>
<div id="box2">There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.</div>
<div id="box3">There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.</div>
<div id="box4">There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.</div>
<div id="box5">There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
div p{ background: aqua}
div ul {background: darkred}
div ul li {background: orchid}
</style>
</head>
<body>
<div>
<p>내가 좋아하는 분식</p>
<ul>
<li>탕수육</li>
<li>족발 및 수육</li>
<li>민초 떡볶이</li>
</ul>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>글자태그</title>
</head>
<body>
<h2>단락과 줄바꿈 : p, br</h2>
<hr>
<p>인터넷상의 정보를 하이퍼텍스트 방식과 멀티미디어 환경에서 검색할 수 있게 해주는 정보검색 시스템이다.
하이퍼텍스트 형식으로 표현된 인터넷상의 다양한 정보를 효과적으로 검색하는 시스템으로 전 세계적으로 가장 널리 보급되어 있다.[1]</p>
<p>하이퍼텍스트는 웹 브라우저라 불리는 프로그램을 통해 웹 서버에서 "문서"나 웹 페이지등의 정보 조각을 읽어들여 컴퓨터 모니터에 출력하는 형태로 보이게 된다.
그러고 나서 사용자는 각 페이지에 있는 하이퍼링크를 따라 다른 문서로 이동하거나, 그 페이지를 서비스하고 있는 서버로 일련의 정보를 보낼 수도 있다.
하이퍼링크를 따라 이동하는 행위를 흔히 웹 서핑(web surfing, 문화어: 망유람[2]) 또는 웹 브라우징이라 한다.</p>
<p>그리고 관련된 내용들이 모여있는 웹 페이지들의 집합을 웹 사이트라 한다.
영어 단어 월드와이드(worldwide)는 보통 공백이나 하이픈 없이 한 단어로 쓰이지만, 월드 와이드 웹(World Wide Web)과 그 약어인 WWW는 공식적인 영어 낱말로 사용되고 있다.</p>
<p>월드 와이드 웹은 다음의 세가지 기능으로 요약할 수 있겠다.
첫 번째 통일된 웹 자원의 위치 지정 방법 예를 들면 URL. 두 번째 웹의 자원 이름에 접근하는 프로토콜(protocol) 예를 들면 HTTP, 세 번째 자원들 사이를 쉽게 항해 할 수 있는 언어 예를 들면 HTML.[3]</p>
<p>MMORPG 월드 오브 워크래프트의 고블린 NPC들이 입에 담는 대사. 백문이 불여일견. 들어보자.<br>
이 고블린 NPC의 성우는 푸우로 유명한 이윤선. 변형판으로 "시간은 금이야, 친구!" 도 있다.<br>
"금이라구"는 좀 진중한 고블린이, "금이야"는 경박한 고블린이 주로 사용한다.<br>
여성 고블린은 "시간은 금이라구요, 금!" 이라 한다.
</p>
</body>
오늘 학원에서 온라인 강의 시험이 가상 환경에서 DB 생성하는 실기 온라인 시험 대비해서 하루 특강으로 선생님이랑
VMWARE를 설치하고 그 환경속에서 PUTTY를 이용해서 DB를 만드는 걸 해보았는데 일단 살짝 묻지 마 코딩식으로 수업을 배워서 정확하게 설치하는 과정 속에서 세세하게.. 아니 설명을 완벽하게 못하는데 순서 정도는 이렇게 진행되는구나 하고 익혔던 시간이었던 거 같다. 그래도 내용이 빈약해도 부족해도 이렇게 기록을 해두면 미래의 나에게 약간의 참조할 도움이 되지 않을까 하고 과정을 복습할 겸 올려보겠다.
일단 우선 첫번째로 CentOS7 버전을 다운로드하여 VMWARE에서 가상 환경에 설치할 것이다.
centos.org
centOS홈페이지에서 다운로드 탭에서 7버전 minimal.iso 파일을 다운로드하고 vmware를 설치한다.
vmware는 14.8버전으로 선생님이 미리 파일을 준비해주셔서 그 걸이 용해서 다운로드하였고 30일 무료 기간을 활용해서 사용하였다. 그렇게 설치한 vmware workstation을 설치하면 가상 환경을 만들 수 있다.
create a new virtual machine 선택
ios 파일을 통해 설치하기 때문에 3번째 체크
리눅스 설치 version은 아까 다운받은 centos7로컬 컴퓨터의 네트워크를 사용할꺼기 때문에 2번째 체크
추천된다고 써있음..ㅋ ㅈㅅ 모름 그냥 next하라고했는데 저게 보통적으로 쓰이나봅니다.
이것도..ㅋ가상 하드만드는거 같습니다.하하하ㅏ20기가를 할당한다고 하네요설정이 끝나면 나오는 화면플레이버튼으로 실행시키면 나오는 화면다운받았던 iso centos파일을 넣기 이거해야 깔립니다깔리는중 글들이 후룩후룩 넘어갑니다한국인이니까 한국말 설정저거 세개를 설정했습니다. 하드는 요로코롬네트워크는 이러코롬kdump는 이러코롬다음을 넘어가면 root(관리자?)의 암호설정을 하는것과 사용자 생성 탭이 있는데 이때 관리자라고 하는 root는 계정 디폴트값이 root라고 합니다. 오른쪽의 사용자 생성 탭으로 원하는 아이디와 비밀번호를 입력해주세요 저는 헷갈려서 괜히 123456 통일했습니다.
요로코롬 사용자생성해주고이러코롬 root(관리자)아이디 비번도 생성해줍니다.그러면 재부팅버튼이 활성화되는데 재부팅하면 리눅스가 깔린것을 확인할수 있습니다.재부팅하면 이렇게 로그인창이 나오는데 리눅스 시스템은 여러 사용자가 동시에 시스템을 이용하는 다중 사용자환경이라서 각 사용자가 시스템을 이용하려면 사용자명과 비밀번호를 이용한 인증이 필요합니다. 그래서 아까 만들어놓은 사용자 계정으로 로그인하면 $달러 표시를 확인할수 있는데 이는 일반사용자의 명령어를 사용할수 있다고 합니다.관리자는 # 우리는 db를 putty로 만들기 위해서 가상환경의 ip주소가 필요합니다 이를 위해서는 관리자 아이디로 변경을 해야하는데 변경하기 위해서는 사용자 변경을 하기위한 명령어인 sur 을 이용해 root 관리자로 바꾸겠슴둥이렇게 관리자 root로 로그인을 합니다. password칸에 비번입력하면 아무것도 안뜨는데 당황하지말고 그냥 쭉 치고 엔터하면 로그인됩니다 그리고 아래에 보면 inet 다음에 써있는 ip주소가 적혀있는데 이를 우리가 사용할 ip주소입니다. 이후로는 putty를 이용해 하겠습니다 개졸립니다
putty 다운로드 후 putty를 실행시켜봅시다
아까 inet ip주소를 써주고 임의의 이름을 세션명에다 적어주고 저장누르면 연결되어서 명령창이 나오는데 여기서 명령어를 통해 db를 만들어보겠습니다
만든 세션을 오픈하면 명령창이 나오는데 여기서 만들어놓은 사용자로 로그인하면 앞서 가상환경에서도 확인할수 있듯이 $모양으로 일반사용자모드? 라는걸 확인할수 있다. 우리는 db서버를 만드는것은 관리자모드에서 진행 되기 때문에 관리자모드로 변경하기위해 su를 입력후 관리자아이디인 root의 비밀번호입력을하면 관리자모드로 바뀌었다는 #을 확인할수있따.
이렇게 확인이 되면 우리는 Mariadb 클라이언트/서버를 설치해야 하는데 설치방법으로는 yum을 이용할 것인데 이게 내가 수업시간에 듣기로는 음 파일을 따로 갖고 다니면서 설치하기에는 번거로움이 있는데 mariadb서버를 접속해 클라이언트/서버를 받아오는 방식으로 들었다. 그래서 mariadb홈페이지에서 서버에 접속하는 코드를 복사를 해와서 명령 창에 넣어주면 된다. 이 방법은 파일을 갖고다니느 번거로움은 없지만 네트워크가 반드시 연결이 되어있어야 한다는 조건이 있다. 이 말이다~
이부분
# MariaDB 10.3 CentOS repository list - created 2020-12-21 03:16 UTC
i를 누르면 insert가 활성화되고 이 부분을 복사해서 넣어준 후 esc를 눌러주면 종료가 되고 이때
저장하고 나가 주는 명령어인 :wq를 사용해야 저장이 된다.
설치하기위해 빨간줄의 명령어를 실행해준다
그럼 우리가 앞서 리눅스 설치할 때처럼 글자들이 후루루룩 지나가는 것을 확인할 수 있는데 잘 설치되고 있는 모습을 볼 수 있따리
complete!를 확인하면 완벽히 설치가 되었다.
이제 mariaDB의 인코딩 설정 및 서버를 시작해보겠다.
이부분은 항목까지 만들어줘야함 눈씻고 찾아봐도 없다.
이역시 수정을 하려면 i를 눌러 insert를 활성화시킨 후 수정후 esc -> :wq 를통해 저장까지 끝 맞춰야 한다.
변경한걸 시작하고 활성화하는
mariadb 기본 설정
위의 설명대로 진행하면 고맙다고 하는 말을 볼수있따 이제 마리아 디비 기본사용자를 추가해보자
MariaDB 기본 사용자 추가
이렇게 쿼리문을 작성해서 db도 만들고 계정을 만들었으면 바로 접속을 할 수 있을 줄 알았지만 그것이 아니다 방화벽 설정을 또 해줘야 한다고 한다
여느때와 똑같이 인서트 활성화해서 값을 넣어주고 esc -> :wq로 저장을 진행한다.
8. 방화벽 관리 도구 설치 및 재시작
dbeaver를 이용해서
서버 호스트를 아까 inet의 ip주소를 가져오고 위에서 쿼리문 작성했던 그대로 로그인 시도하면 로그인이 되는 것을 확인할 수 있다. 대충 순서는 이러하다 . 그런데 명령문에 대한 숙지가 안되어있는 상태로 수업이 진행되서 그런지 이해하는데 혼선이 되게 많았던거 같다. 복습을 통해서보면 그저 순서대로 과정을 진행한것밖에 없는데 웹도 배워야하고 해야할게 천지인데 대충 이정도 순서로 진행되어서 로컬환경의 pc가 아니더라도 putty를 통해 외부 컴퓨터에서도 접속을 할 수 만들수있음을 확인할수 있는 시간이 되었다. 아 졸리다 졸리다 나중에는 좀 더 명령문에 대한 기본 숙지나 리눅스를 심도 있게 보는 기회가 생긴다면 살을 더 붙여서 좋은 정보가 되게 만들어봐야겠다
선생님이 수업시간에 만들 삼광기업? 이라는 임의의 회사 테이블 사진과 데이터 파일을 주셔서 그걸 기반으로 수업시간에 만들어 보았는데 전에 수업전에 만든 JDBC와 VO클래스를 필요할때마다 만드는 점이 달랐던거 같다. 집에서도 복습을 해보고 기존에 만들어놓은 코드들을 안보고 백지상태에서 써보면 뭔가 뿌듯할거 같아서 최대한 참고를 안해보고 복습 해보겠다. 백지가아닌건가 양심적으로 최대한 안보고 작성해보겠다.
작성순서는 메인클래스에다 서비스클래스를 인스턴스후 서비스 클래스 안에 있는 디스플레이 메서드를 띄우고 나서 숫자 입력시 정해놓은 메서드가 실행되게 switch문을 작성한다. 이렇게 작성하면 서비스 클래스와 서비스 클래스 내부의 메서드가 생성되어있지 않는 상태여서 오류가 나오면서 빨간줄이 가게될텐데 이때 나는 IDE의 오류해결기능? 을 이용해서 클래스와 메서드를 생성하는데 생각보다 개꿀이다. 오류가난 빨간줄에 빨간전구를 클릭하면 오류 해결대책으로 여러가지 선택지가 있는데 거기서 클래스생성,메서드생성등을 입맛에 골라 선택하면 바로바로 만들어준다 이번에 만들때는 전체적인 틀에서 세부적인 기능을 넘어가게 만들어 보았다. 예를들어 삼광의 전체 테이블중 직원테이블을 관리하고자 인사관리라는 메뉴를 만들고 인사관리 메뉴를 선택하면 그안에 또 세부적인 인사추가 / 인사조회 라던지 이런 메뉴들이 나누어 지도록 일단 머리로 돌렸을때는 switch/case 문 안에다 IF 문을 이용해서 해봤는데 잘된다
package day12_20;
import java.util.Scanner;
public class SamKwangMain {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
SamKwangService sv = new SamKwangService();
sv.displaymenu();
int button = Integer.parseInt(sc.nextLine());
while(true) {
switch (button) {
case 1:
sv.employeeMenu();
button = Integer.parseInt(sc.nextLine());
if (button==1){
sv.newEmployee();
}else if(button==2){
sv.readEmployee();
}else if(button==3){
sv.readOneEmployee();
}else sv.displaymenu();
break;
case 2:
break;
case 3:
break;
case 0:
System.exit(0);
break;
}
}
}
}
이후 서비스 만들어지 서비스 클래스에서 콘솔창에 나올 디스플레이 메뉴 메서드들을 만들고
newEmployee() 메서드를 이용해 새로운 인사정보를 받는 메서드를 작성하는데 작성하는데 있어
인사정보의 값들을 DB에 전달해주기 전에 담아둘 그릇이 필요한데 이때 VO클래스를 생성해서 직원테이블을 참조해 직원 테이블에 있는 컬럼값들을 담을 변수들을 선언해준다. 이역시 오류해결기능을 이용하면 번거롭게 다시 프로젝트창에서 클래스 생성을 안해주어도 된다. 개꿀
VO클래스 생성해서 생성자와 getter/setter 를 생성해주자
package day12_20;
public class SamKwangVO {
private int 인사번호;
private String 주민등록번호;
private String 성명;
private String 소속부서;
private String 직책;
private String 인사일;
public SamKwangVO() {
}
public SamKwangVO(int 인사번호, String 주민등록번호, String 성명, String 소속부서, String 직책, String 인사일) {
this.인사번호 = 인사번호;
this.주민등록번호 = 주민등록번호;
this.성명 = 성명;
this.소속부서 = 소속부서;
this.직책 = 직책;
this.인사일 = 인사일;
}
public SamKwangVO(int 인사번호, String 성명, String 소속부서, String 직책) {
this.인사번호 = 인사번호;
this.성명 = 성명;
this.소속부서 = 소속부서;
this.직책 = 직책;
}
public int get인사번호() {
return 인사번호;
}
public void set인사번호(int 인사번호) {
this.인사번호 = 인사번호;
}
public String get주민등록번호() {
return 주민등록번호;
}
public void set주민등록번호(String 주민등록번호) {
this.주민등록번호 = 주민등록번호;
}
public String get성명() {
return 성명;
}
public void set성명(String 성명) {
this.성명 = 성명;
}
public String get소속부서() {
return 소속부서;
}
public void set소속부서(String 소속부서) {
this.소속부서 = 소속부서;
}
public String get직책() {
return 직책;
}
public void set직책(String 직책) {
this.직책 = 직책;
}
public String get인사일() {
return 인사일;
}
public void set인사일(String 인사일) {
this.인사일 = 인사일;
}
}
vo클래스를 작성했으면 다시 service 클래스로 돌아와서 vo클래스를 인스턴스해서 vo클래스의 생성자를 이용하여 입력받은 값들은 vo클래스에 넣어준다.
DB에 값을 전달해주는 DAO클래스의 메서드를 이용하는 코드를 작성하고 이때 매개변수로 아까 위에서 vo클래스를 인스턴스한 객체로 설정해준다.
package day12_20;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Scanner;
public class SamKwangService {
// 메뉴화면
public void displaymenu() {
StringBuilder sb = new StringBuilder();
sb.append("-----삼광관리프로그램V1-----\n")
.append("1.인사관리 실행\n")
.append("2.미정\n")
.append("3.미정\n")
.append("0.프로그램종료\n")
.append("입력 : ");
System.out.println(sb);
}
// 인사관리 화면
public void employeeMenu() {
StringBuilder sb = new StringBuilder();
sb.append("1. 인사정보 추가\n")
.append("2.인사정보 조회\n")
.append("3.인사정보 상세조회\n")
.append("종료시 아무키 (1/2/3/ 제외)\n")
.append("입력 :");
System.out.println(sb);
}
public void newEmployee() {
SamKwangVO vo = new SamKwangVO();
Scanner sc = new Scanner(System.in);
System.out.print("인사번호 입력 :");
vo.set인사번호(Integer.parseInt(sc.nextLine()));
System.out.print("주민등록번호 입력 :");
vo.set주민등록번호(sc.nextLine());
System.out.print("성명 입력 :");
vo.set성명(sc.nextLine());
System.out.print("소속부서 입력 :");
vo.set소속부서(sc.nextLine());
System.out.print("직책 입력 :");
vo.set직책(sc.nextLine());
System.out.print("입사일 입력 :");
vo.set인사일(sc.nextLine());
String result = SamKwangDAO.insertEMP(vo);
System.out.println(result);
}
public void readEmployee() {
ArrayList<SamKwangVO> emps = new ArrayList<>();
emps = SamKwangDAO.readEmp();
String fmt = "인사번호 :%s 성명 :%s 소속부서 :%s 직책 :%s\n";
StringBuilder sb = new StringBuilder();
for(SamKwangVO emp : emps){
String result = String.format(fmt,emp.get인사번호(),emp.get성명(),emp.get소속부서(),emp.get직책());
sb.append(result);
}
System.out.println(sb.toString());
}
public void readOneEmployee() {
}
}
dd
아까 위에서 설명했듯이 DAO에 빨간줄이 갈텐데 이때 오류해결기능으로 클래스/메서드 둘다 생성후 DAO클래스로 돌아가서 DB에 연결하는 코드를 작성해준다.
conn.preparestatement 쪽을 보면 jdbc클래스에 연결되어있는 변수를 가져다 쓰는걸 볼 수 있는데 jdbc 클래스에 db에 동작할 쿼리문을 String 변수를 하나 만들어 거기다 저장해놓았다. 이때 preparedstatement를 이용하면 보안에도 좋고 효율도 좋다고 한다. . 보안은 쿼리문에 입력받을 부분을 '?' 으로 표현해서인거 같고 효율은 좋다고하니 그런갑다 하고있다.
package day12_20;
public class SamKwangJDBC extends JDBCUtil{
public static String insertEmployee =
"insert into 직원 (인사번호, 주민등록번호, 성명, 소속부서, 직책, 입사일) values ( ?,?,?,?,?,?)";
public static String readEMP=
"select 인사번호,성명,소속부서,직책 from 직원";
}
학원에서 자바와 mysql을 맛보기(?) 식으로 공부를 어느정도 진행되고 오늘 JDBC를 이용해 성적프로그램을
간단하게 만들어 보았고 혼자 실습(?)하는 느낌으로 사원정보 프로그램을 만들어보려고 한다.
보다가 주옥같은 부분이 있다면 말해주길.. 못알아들을수도 있는건 함정
JDBC ( java database connectivity ) :
자바를 통해 다양하고 관계형 데이터베이스에 접속하고
SQL문을 실행해서 관리하고자 할때
사용하는 표준 SQL인터페이스
이것을 통해 데이터베이스 코드를 한번만 작성해두면
어떤 DBMS라도 코드 변경 없이 동일하게 작동시킬 수 있음
JDK에 포함된 JDBC 인터페이스는 java.sql 패키지 아래에 있음
하지만, 이것만으로는 작동하지 않고
JDBC 인터페이스에 맞게 각 데이터베이스 제조사가
구현한 JDBC 클래스들이 필요한데,
이것을 JDBC 드라이버라고 함.
JDBC드라이버들은 제조사 홈페이지에서 내려받을수 있음.
mariadb.org
1. DB 테이블 생성
mariaDB 전용 스크래치 파일을 만들어 간단한 테이블 생성 코드를 작성
create table EmployeeManage (
empno int auto_increment, -- 사원번호는 자동증가하게 설정
fname varchar(255), -- 미국식 이름으로 설정 ㅋ ㅈㅅ
lname varchar(255),
email varchar(255),
phone varchar(255),
hdate varchar(255), -- 입사일
jobid varchar(255), -- 직책번호
sal int, -- 연봉
comm decimal(5,2), -- 수당
mgrid int, -- 사수 사원번호
deptid int, -- 부서번호
date timestamp default current_timestamp(), -- 데이터 기록날짜/시간
primary key (empno) -- 사원번호를 기본키로 설정
);
2. EmployeeUtil 클래스 만들기
DB를 접속하여 리소스(테이블)에 접근하고 작업이 끝나면 접속해제(?)하는 메서드를 구현 하기 위한 클래스
접속하기 위해서는 각각 맞는 드라이버 파일을 자바폴더에 설치해서 IDE에서 라이브러리 추가해주어야함
라이브러리 추가
package semiproject12_16;
import javax.xml.transform.Result;
import java.sql.*;
public class EmployeeUtil {
// DB접속 하기
public static Connection makeConn(){
String DRV = "org.mariadb.jdbc.Driver"; //드라이버 내용고정이라서 외워주면 좋음?
String URL = ""; // AWS RDS를 이용중인데 여기 엔드포인트 주소를 적어줘야함
// “jdbc:Driver 종류://IP:포트번호/DB명”
String USR = ""; // DB 사용자 계정
String PWD = ""; // DB 비번 보안상의 이유로 비워놓았다.
Connection conn=null; // 데이터베이스와 연결하는 객체
try {
Class.forName(DRV); // Class.forName 을 이요해 드라이버 로드
conn = DriverManager.getConnection(URL,USR,PWD); //DB접속하기
} catch (ClassNotFoundException e) {
System.out.println("드라이버 접속 오류");
} catch (SQLException throwables) {
System.out.println("DB접속 오류");
}
return conn;
}
// DB연결 해제
public static void destroyConn(Connection conn, PreparedStatement pstmt, ResultSet rs){
if (conn != null) try { conn.close(); } catch (SQLException throwables) { }
if (pstmt != null) try { pstmt.close(); } catch (SQLException throwables) { }
if (rs != null) try { rs.close(); } catch (SQLException throwables) { }
}
// DB연결 해제2 (데이터 입력 메서드에서 사용하기위해 추가생성)
public static void destroyConn(Connection conn, PreparedStatement pstmt ){
if (conn != null) try { conn.close(); } catch (SQLException throwables) { }
if (pstmt != null) try { pstmt.close(); } catch (SQLException throwables) { }
}
}
3. EmployeeJDBC 클래스 생성 후 EmployeeUtil 클래스 상속받기
JDBC클래스에서는 MySql 코드를 String 변수를 static 으로 선언하여 저장해두고
DB에 데이터를 입력하거나 조회하는 메서드 안에서 작업하기 위해 만들어 둔다
또한 기존에 만들어놓은 Util 클래스에서의 DB접속/해제 기능을 한개의 클래스에서 사용하기 위해
상속을 해준다.
package semiproject12_16;
public class EmployeeJDBC extends EmployeeV2Util{
// 데이터입력 하기위한 쿼리문 , 동적쿼리문(PreparedStatement)으로 구현
public static String insertEmployee =
"insert into EmployeeManage (empno,fname,lname,email,phone,hdate,jobid,sal,comm,mgrid,deptid) values" +
"(?,?,?,?,?,?,?,?,?,?,?)";
// 사원의 모든 정보 조회 쿼리문
public static String selectEmployee =
"select * from EmployeeManage";
// 특정사원 정보 조회 쿼리문
public static String selectOneEmployee =
"select * from EmployeeManage where empno = ?";
}
4. EmployeeVO클래스 생성하기
VO( Value Object):
데이터베이스 테이블 값들을 자바에서 변수로 만들어 놓은것 ?
package semiproject12_16;
public class EmployeeVO {
private int empno;
private String fname;
private String lname;
private String email;
private String phone;
private String hdatd;
private String jobid;
private int sal;
private double comm;
private int mgrid;
private int deptid;
private String date;
public EmployeeVO() {
}
public EmployeeVO(int empno, String fname, String lname, String email, String phone, String hdatd, String jobid, int sal, double comm, int mgrid, int deptid) {
this.empno = empno;
this.fname = fname;
this.lname = lname;
this.email = email;
this.phone = phone;
this.hdatd = hdatd;
this.jobid = jobid;
this.sal = sal;
this.comm = comm;
this.mgrid = mgrid;
this.deptid = deptid;
}
public EmployeeVO(int empno, String fname, String lname, String email, String phone, String hdatd, String jobid, int sal, double comm, int mgrid, int deptid, String date) {
this.empno = empno;
this.fname = fname;
this.lname = lname;
this.email = email;
this.phone = phone;
this.hdatd = hdatd;
this.jobid = jobid;
this.sal = sal;
this.comm = comm;
this.mgrid = mgrid;
this.deptid = deptid;
this.date = date;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getHdatd() {
return hdatd;
}
public void setHdatd(String hdatd) {
this.hdatd = hdatd;
}
public String getJobid() {
return jobid;
}
public void setJobid(String jobid) {
this.jobid = jobid;
}
public int getSal() {
return sal;
}
public void setSal(int sal) {
this.sal = sal;
}
public double getComm() {
return comm;
}
public void setComm(double comm) {
this.comm = comm;
}
public int getMgrid() {
return mgrid;
}
public void setMgrid(int mgrid) {
this.mgrid = mgrid;
}
public int getDeptid() {
return deptid;
}
public void setDeptid(int deptid) {
this.deptid = deptid;
}
}
5. 인터페이스, 제네릭클래스 생성후 데이터입력,조회 메서드를 작성할 서비스 클래스 생성하기.
package semiproject12_16;
import java.sql.*;
public abstract class EmployeeInterface {
// 새로운 사원 입력 메서드
public abstract void newEmployee();
// 사원조회 메서드
public abstract void readEmployee();
// 특정사원 조회 메서드
public abstract void readOneEmployee();
}
// 제네릭클래스 생성 후 인터페이스 상속
// 생성이유는 인터페이스에서 만들어놓은 메서드들은 재정의? 가 꼭 필요한데 제네릭클래스에서
// 재정의후 서비스클래스에서 상속을통해 편리하게 필요한 메서드만 가져와 정의를 내릴수 있다
package semiproject12_16;
public abstract class EmployeeGenericClass impelements EmployeeInterface {
@Override
public void newEmployee() {
}
@Override
public void readEmployee() {
}
@Override
public void readOneEmployee() {
}
@Override
public void modifyEmployee() {
}
@Override
public void removeEmployee() {
}
}
6. EmployeeService, EmployeeDAO 클래스 생성하기
package semiproject12_16;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Scanner;
public class EmployeeService extends EmployeeGenericClass{
public void displayMenu(){
StringBuilder sb = new StringBuilder();
sb.append("-------------------\n")
.append("인사정보 처리프로그램 v1\n")
.append("-------------------\n")
.append("1. 인사 정보 입력\n")
.append("2. 인사 정보 조회\n")
.append("3. 인사 정보 상세조회\n")
.append("4. 인사 정보 수정\n")
.append("5. 인사 정보 삭제\n")
.append("0. 프로그램 종료\n")
.append("-------------------\n")
.append("원하시는 작업은 ? [1,2,3,4,5,0] ");
System.out.print(sb);
}
// 데이터입력 메서드
// DB에 데이터값 넣는메서드는 DAO클래스에서 정의
@Override
public void newEmployee() {
int empno;
String fname;
String lname;
String email;
String phone;
String hdatd;
String jobid;
int sal;
double comm;
int mgrid;
int deptid;
Scanner sc = new Scanner(System.in);
System.out.print("사번을 입력하세요 : ");
empno = Integer.parseInt(sc.nextLine());
System.out.print("이름을 입력하세요 : ");
fname = sc.nextLine();
System.out.print("성을 입력하세요 : ");
lname = sc.nextLine();
System.out.print("이메일을 입력하세요 : ");
email = sc.nextLine();
System.out.print("전화번호를 입력하세요 : ");
phone = sc.nextLine();
System.out.print("입사일을 입력하세요 : ");
hdatd = sc.nextLine();
System.out.print("직책을 입력하세요 : ");
jobid = sc.nextLine();
System.out.print("급여를 입력하세요 : ");
sal = sc.nextInt();
System.out.print("수당 입력하세요 : ");
comm = sc.nextInt();
System.out.print("상사번호를 입력하세요 : ");
mgrid = sc.nextInt();
System.out.print("부서번호를 입력하세요 : ");
deptid = sc.nextInt();
EmployeeV2VO emp = new EmployeeV2VO(empno,fname,lname,email,phone,hdatd,jobid,sal,comm,mgrid,deptid);
String result = EmployeeV2DAO.insertEmployee(emp); // DAO클래스참조
System.out.println(result);
}
// 조회할 성적데이터를 DAO로부터 넘겨받아 출력
@Override
public void readEmployee() {
String fmt = "사원번호 : %s, 성 :%s, 이름 :%s, 이메일 :%s, 전화번호 :%s, 입사일 :%s, 직책 :%s 급여 :%s 수당 :%s, 사수 :%s, 부서번호 :%s, 데이터추가일 :%s\n";
StringBuilder sb = new StringBuilder();
ArrayList<EmployeeV2VO> emps = EmployeeV2DAO.selectEmployee();
for(EmployeeV2VO emp : emps){
String result = String.format(fmt,emp.getEmpno(),emp.getFname(),emp.getLname(),emp.getEmail(),emp.getPhone(),emp.getHdatd(),emp.getJobid(),emp.getSal(),
emp.getComm(),emp.getMgrid(),emp.getDeptid(),emp.getDate());
sb.append(result);
}
System.out.println(sb.toString());
}
// 특정사원 정보 출력
@Override
public void readOneEmployee() {
String fmt = "사원번호 : %s, 성 :%s, 이름 :%s, 이메일 :%s, 전화번호 :%s, 입사일 :%s, 직책 :%s, 급여 :%s 수당 :%s, 사수 :%s, 부서번호 :%s, 데이터추가일 :%s\n";
Scanner sc = new Scanner(System.in);
System.out.print("조회할 사원의 사원번호는 ? :");
String empno = sc.nextLine();
// DAO클래스에 위에서 받은 조회할사원번호를 매개변수로 보내주기
EmployeeV2VO emp = EmployeeV2DAO.selectOneEmployee(empno);
// DAO클래스의 메서드로 받아온 값들을 출력
String result = String.format(fmt,emp.getEmpno(),emp.getFname(),emp.getLname(),emp.getEmail(),emp.getPhone(),emp.getHdatd(),emp.getJobid(),emp.getSal(),
emp.getComm(),emp.getMgrid(),emp.getDeptid(),emp.getDate());
System.out.println(result.toString());
}
}
package semiproject12_16;
import stillgood96.SungJukJDBC;
import java.sql.*;
import java.util.ArrayList;
public class EmployeeDAO {
// EmployeeService에서 입력받은 데이터값들을 매개변수로 받는 메서드로 생성
public static String insertEmployee(EmployeeV2VO emp) {
// 연결객체 생성
Connection conn = null;
// DB쿼리문 실행하기위한 객체 생성
PreparedStatement pstmt = null;
// 데이터의 입력 유/무 알리기위한 result변수 선언
String result = null;
// JDBC(util을상속받음)에 상속받은 util의 makeConn 메서드이용해서 드라이버 로드 및 DB접속
conn = EmployeeV2JDBC.makeConn();
try {
// JDBC에 작성한 데이터입력 쿼리문 가져오기
pstmt = conn.prepareStatement(EmployeeV2JDBC.insertEmployee);
// 서비스클래스에서 매개변수로 받아온 데이터값을 넣기
pstmt.setInt(1,emp.getEmpno());
pstmt.setString(2,emp.getFname());
pstmt.setString(3,emp.getLname());
pstmt.setString(4,emp.getEmail());
pstmt.setString(5,emp.getPhone());
pstmt.setString(6,emp.getHdatd());
pstmt.setString(7,emp.getJobid());
pstmt.setInt(8,emp.getSal());
pstmt.setDouble(9,emp.getComm());
pstmt.setInt(10,emp.getMgrid());
pstmt.setInt(11,emp.getDeptid());
int cnt = pstmt.executeUpdate();
if (cnt>0)
result = "성적데이터 저장완료!";
} catch (SQLException throwables) {
System.out.println("DB 데이터 추가완료!");
}
EmployeeV2JDBC.destroyConn(conn,pstmt);
return result;
}
// 사원정보들을 동적배열에 저장해서 넘긴다.
public static ArrayList<EmployeeV2VO> selectEmployee() {
ArrayList<EmployeeV2VO> emps = new ArrayList<>();
Connection conn = null;
PreparedStatement pstmt = null;
// ResultSet
// select(조회)의 결과를 저장하는 객체
ResultSet rs = null;
conn = EmployeeV2JDBC.makeConn();
try {
pstmt = conn.prepareStatement(EmployeeV2JDBC.selectEmployee);
rs = pstmt.executeQuery();
// 반복문으로 모든 데이터를 가져오게 설정
while(rs.next()){
EmployeeV2VO emp= new EmployeeV2VO(
rs.getInt(1),
rs.getString(2),
rs.getString(3),
rs.getString(4),
rs.getString(5),
rs.getString(6),
rs.getString(7),
rs.getInt(8),
rs.getDouble(9),
rs.getInt(10),
rs.getInt(11),
rs.getString(12) );
emps.add(emp); // 행을 다읽어올때마다 동적배열에 저장후 다시 그다음행 읽어오기
}
} catch (SQLException throwables) {
System.out.println("selectEmployee 에서 오류 발생");
}
EmployeeV2JDBC.destroyConn(conn,pstmt,rs);
return emps;
}
// 특정사원 정보 긁어오기
// 서비스에서 받아온 특정사원번호를 매개변수로 받는 메서드로 생성
public static EmployeeV2VO selectOneEmployee(String empno) {
Connection conn = null;
PreparedStatement pstmt = null;
EmployeeV2VO emp = null;
ResultSet rs = null;
conn = EmployeeV2JDBC.makeConn();
try {
pstmt = conn.prepareStatement(EmployeeV2JDBC.selectOneEmployee);
pstmt.setString(1,empno);
rs= pstmt.executeQuery();
// 한개의 값만 가져오면 되니까 if문
if(rs.next()){
emp = new EmployeeV2VO(
rs.getInt(1),
rs.getString(2),
rs.getString(3),
rs.getString(4),
rs.getString(5),
rs.getString(6),
rs.getString(7),
rs.getInt(8),
rs.getDouble(9),
rs.getInt(10),
rs.getInt(11),
rs.getString(12)
);
}
} catch (SQLException throwables) {
System.out.println("selectOneSungJuk 에서 오류발생!");
throwables.printStackTrace();
}
SungJukJDBC.destroyConn(conn,pstmt,rs);
return emp;
}
}
결과출력
결과출력창을 다시보니
조회할때 테이블처럼 나오도록 양식 변경하면 좋을 것 같고
수업시간에 mysql 하다가 꽤 오랜시간 후에 다시 자바를 하는거여서 낯설기도 하고
새로운 부분을 타이트한 일정때문인지 훅훅 지나가서 묻지마 코딩으로 선생님 코딩을 옮겨쓰고 있었는데
이렇게 블로그에 정리하면서 코드들을 다시 봐보니 이해가 어느정도 간다 과연 백지상태에서 이렇게 다시 쓸수있을까
그래서 수업이 끝나고 따로 시간을 내서 유튜브로 생활코딩 '자바예외처리' 강의를 듣고 코딩을 따라 쓰고
내용을 정리해보았다. 같은 파트를 다른 영상으로 같은 내용이지만 다른 설명으로 2회차를 들으니 갈피가 서는 느낌이
많이 들어서 지루하지 않고 나름 재밌게 잘들었다.
package day12_14;
public class ExceptionApp {
//1
// 자바에서는 0을 나눌수 없다 그래서 오류가 뜬다.
// 허나 어떤 프로그램은 24시간 돌아가야한다면
// 이런 오류를 만나 프로그램이 작동이 안하면 난감할 것이다.
// 이럴때 예외처리를 통해 오류가 발생하여도 그다음 프로그램이 작동하게
// 하는 것도 예외처리의 한 방법이 될 수 있다
//2
// 아래를 보면 알수있듯이 2를0으로 나누면 자바에서는 오류가 나오는데(ArithmeticException)
// 이럴때 예외처리인 try /catch문으로 감싸면 오류를 예외처리로 처리하고
// catch문을 작성할때 오류에 맞는 예외처리를 넣는것이 좋다. 그리고
// 안에 있는 코드를 실행후 그다음 코드가 실행되는 것을 볼 수 있다.
//3
// 하나의 try문의 예외처리할 문장을 여러개 넣는다면
// 첫번째 예외처리문을 만났을때 catch문을 실행후
// 바로 try/catch문을 빠져나간다. 그 다음 예외처리할 문장이
// 실행조차 안되는 것 같다.
public static void main(String[] args) {
//1
System.out.println(1);
try {
System.out.println(2 / 0); // ArithmeticException
}catch(ArithmeticException e){
System.out.println("잘못된 계산이네요");
}
System.out.println(3);
System.out.println(4);
//2
int [] scores = {10,20,30}; // 배열의 저장범위 바깥 데이터를 가져오려 할 때
try {
System.out.println(scores[3]); // ArrayIndexOutOfBoundsException
}catch(ArrayIndexOutOfBoundsException aiob){
System.out.println("없는 값을 찾고 계시네요~ ^^");
}
//3
try {
System.out.println(10);
System.out.println(2 / 0);
int[] scores2 = {10, 20, 30};
}catch(ArithmeticException e2){
System.out.println("헛짓거리하시네 ~");
}catch(ArrayIndexOutOfBoundsException ad){
System.out.println("그러게말여~");
}
System.out.println(15);
}
}
package day12_14;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class CheckedExceptionApp {
// IOException 을 발생시키는 코드를 발생해 보겠다
// Checked exception vs unchecked exception
// 전자의 경우 대표적으로 IOException이 있다.
// 전자의 경우 컴파일러에서 직접 예외처리를 했는지 검사하기 때문에
// 반드시 코드에서 예외 처리를 해주어야 한다.
// 후자의 경우
// 앞선 'Exception' 클래스에서 볼 수 있었던
// ArrayIndexOutOfBoundsException 나 ArithmeticException 와 같은 경우로
// 이와같은 예외처리는 따로 안해도 실행이 가능하지만
// 실행후 오류메세지가 나온는 것을 확인할 수 있다.
// 결과적으로 전자인 checked exception 같은 경우는 예외처리를 코드에서 무조건 해주어야하고
// 후자인 unchecked exception 은 코드 안에서 예외처리를 꼭 안해도 된다는 것
// 또한 이 두가지로 예외처리가 나뉜다는 정도를 알면 좋을 것 같다고 한다 생활코딩 따거께서
public static void main(String[] args) {
try {
FileWriter f = null;
f = new FileWriter("data.txt");
f.write("hello");
f.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package day12_14;
import java.io.FileWriter;
import java.io.IOException;
public class Finally_and_Resource {
// finally 와 resource
// 자바가 외부 프로그램에 엑세스 할때 생길수 있는 예외처리
// 대표적인 외부프로그램(리소스)으로는 파일, 네트워크, 데이터베이스가 있다.
// 다시, 리소스는 자바 내부의 데이터가 아니기에 예외처리가 많이 발생할 수 있다.
// 자바에서 리소스를 사용할때 자바는 리소스를 붙잡는 모종의 행위(?) 들이 있는데
// 파일은 나만 파일을 쓰겠어 .. ? 네트워크는 커넥션.. ? 아무튼 붙잡는 작업을 다하고
// 나면 리소스를 놔줘야하는데 놔주는 코드가 close() 이다.
// close()를 써주기 위해서는 다소 복잡한 과정이 있다.
// 일차적으로 아래에서 filewriter를 쓸때 예외가 발생할 수 있어 try/catch문으로 감싸고
// try문에 close를 쓴다면 try문에서의 예외처리가 발생한다면 close는 실행이 되지 않는다.
// 그렇기에 필요한것은 finally문안에다 close를 써주는 것인데 finally 문은 예외처리가 발생하건 안하건
// 무조건 finally문 안에 있는 내용을 실행시켜주는 것인데 그렇기에 finally 문안에 넣으면 빨간밑줄이 기다리고 있을터인데
// finally를 열고 close문을 쓰면 close가 try문안에서의 지역변수를 받을 수 없어 try문 밖에서 전역변수로 선언을 해야 오류가
// 안나온다. 그렇게 밖에다 또 선언하고 나면 또 빨간줄이 나오는 것을 확인할 수있는데 ~ 이번에는 또 finally 안에서 close를
// 실행하는데 있어서도 예외처리가 나올 수 있다는 것이다. 말은 그렇다 . 그래서 finally 안에서 또 예외처리를 해주어야 한다.
// finally 문 안에서도 예외처리를 또 해주면 비로소 빨간 밑줄을 안보게 될 수 있는데 이와 같은 방법은 너무 복잡하고 장황하다 .
// 이와 같은 방법을 해결하기 위해 try-with-resource 라는 신기술이 있다고 한다.
// try-with-resource
// java7 부터 추가함
// 위에서 봤듯이 위의 방법은 코드가 매우 장황해진다.
// 간단히 쓰는 방법을 사용하면
// 일단 try (close가 필요한 코드) {} catch{} 문
// 이런식으로 써놓으면 알아서 실행후 예외가 발생하건 안하건 마지막에 close를 실행해준다.
// 확연히 위와 간단해진 코드를 확인할 수 있다 .
public static void main(String[] args) {
FileWriter fw=null;
try {
fw = new FileWriter("data2.dat");
fw.write("hello");
} catch (IOException e) {
e.printStackTrace();
} finally{
// 만약에 fw가 null이 아니라면 close를 해라 ~
if(fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// try-with-resource
// try with resource statements
try (FileWriter f = new FileWriter("data.txt")){ // try 괄호 안에다가 close가 필요한클래스를 인스턴스하는 코드 입력
f.write("HELLO");
}catch(IOException e){
e.printStackTrace();
}
}
}
-- 임의의 사원 정보 :
-- 이름 : 이선우
-- 입사일 : 2015-05-06
select '이선우','2015-05-06' 입사일,
date_add('2015-05-06',
interval 7 - dayofweek('2015-05-06')+ 1 day);
-- 풀이
일단 이선우의 입사일은 2015-05-06 이다. 이 날짜를 기준으로 다음주 일요일이 언제인지 구하는 것인데.
5월 6일의 요일을 date_add를 통해 토요일로 만들어야한다. 토요일로 만드는 이유는 초기화의 개념으로 받아들
이면 편한다. 날짜의 기준을 잡을때 어떤 요일이던 토요일로 만들어주고 거기서 원하는 요일의 코드를 dayofweek
함수로 반환해서 초기화한 토요일에 더 해주면 자연스레 다음주의 원하는 요일을 구할 수 있다.
date_add함수를 이용하여 기준날짜로부터 몇일을 추가하는지 interval을 이용해서 일주일인 7일을 기준으로 잡고
일요일로 만들기 위해 dayofweek함수를 이용하여 현재요일의 코드를 반환받아 7에서 빼주면 토요일까지 남은 날짜가
나올 것이고 남은 날짜를 기준날짜에 더해주면 자연스레 토요일이 된다.
토요일이 되고나서 dayofweek 함수로 요일들을 뽑아내면 1: 일요일 2: 월요일 3: 화요일 ...
이렇게 나오는데 원하는 요일인 일요일인 +1을 더해주면 다음주 일요일의 날짜가 출력되는걸 확인할 수 있다.
풀면서 골때렸던 문제가 뭐가 더 있나 훑어봤는데 2일넘게 다 반복적으로 훑어봤던거라 뭔가 다 익숙한 느낌이 난다.
select substr(123456789,5,1);
-- 숫자형 데이터가 자동으로 문자형으로 변환
select 1234567890, cast(1234567890 as char); -- 숫자는 오른쪽정렬 문자형은 왼쪽으로 정렬
-- cast를 char형을 바꿔서 왼쪽정렬해서 출력되는 것을 확인할 수 있다~
select 10/3, 10/'3';
-- 첫번째 값은 float형으로 소수점자리가 4자리까지나오고
-- 두번재 값은 문자가 실수(float)로 자동형변환 되어 더블형으로 소수점자리가 많아지네요잉~
select 10/cast( '3' as signed ),10/cast('3' as float);
select 10/cast('3' as integer), 10/cast('3' as float );
select cast(124035 as time);
select cast(20201210 as date);
-- 시간, 날짜도 변환가능 (단, 정수형태로 작성해야 함)
깃허브를 알게된뒤 부터 블로그에 올리지 않고 바로 깃허브에 학원에서 올린 코드들을 보며 복습해왔는데
확실히 사람이 편해지면 게을러진다. 나만 그런걸수도 있지만 컹스컹스
그전에 올린 글을 보니 DAY1 통합개발환경 구축하는 이클립스를 설치했었는데 친구가 블로그에 복습하면서 하는게 좋다고 해서 나도 한번 다시 블로그에 수업에 했던 내용을 적어 복습할겸 적어본다.
깃허브로 코드들만 보니 뭔가 복습이 제대로 안되고 있다고 느끼기도 해서 컹스컹스방구
일단 오늘 MySQL에서 뷰와 내장함수를 배웠다.
뷰( View) :
1. 다른 테이블을 기반으로 만들어진 가상 테이블
2. 데이터를 실제로 저장X , 논리적 존재하는 테이블 but 일반테이블과 동일한 방법으로 사용
3. 뷰를 통해 기본테이블( 뷰를 만드는 물리적 테이블)의 내용을 쉽게 조회 가능하나 기본테이블의
데이터를 변경하는 것은 제한적이다.
4. order by 정렬 불가능
뷰( View )의 목적 :
1. 특정필드에만 접근 허용( 보안의 목적 )
2. 데이터 조작의 간소화 ( 조인/검색 )
뷰( View ) 생성 코드 :
-- 뷰 생성
create view [뷰이름] as select문
-- 뷰의 이름을 생성후 as 로 뷰에 추가할 테이블을 select 문으로 설정해준다.
-- 뷰를 변경할수도 있다.
alter view [뷰이름] as select문
뷰( View ) 를 이용한 데이터 삽입, 수정,삭제 :
1. 뷰는 원본테이블의 분신이다.
2. 삽입, 수정, 삭제 작업은 원본테이블을 대상으로 진행
단, 수정,삭제는 제한적으로 수행이 될 수 있다.
3. 수정,삭제가 제한적으로 수행이 되는 테이블의 예로 지금 까지 내가 확인한 바로는
테이블에서 컬럼을 뽑아와 뷰를 만든 뷰에서
수정을 하려고 할 때 안뽑아온 나머지 컬럼에 not null 이 적용 되어있으면 수정 불가능하다.
문제) 원본테이블의 부재의 이유는 깃허브에 있다.. 아쉬운 마음에 사진을 첨부해본다...
-- 제품번호가 p08, 재고량이 1000, 제조업체가 신선식품인 새로운 제품의 정보를
-- 제품1 뷰에 삽입해보자. 그런 다음 제품1 뷰에 있는 모든 내용을 검색해보자
create view 제품1 as
select pdNum ,qunatity,company from productTest;
insert into 제품1 values ('p08',1000,'신선식품');
select * from 제품1;
문제2) 뷰를 만들때 여러 테이블을 조인하여 만들 수도 있다..
조인하여 만들면 편하게 데이터를 조회할 수 있는데
아래의 문제가 그렇다.
주문 테이블은 상품테이블과 고객테이블에 외래키를 두고 있다.
그 외래키로 묶인걸 조인해서 뷰를 만들어 놓으면 각각의 테이블의 데이터 값들을 넘나들며 조회할 수 있는데
예를들어 고객테이블의 csid 가 'banana' 인 고객의 이름은 '김선우'이다. 단순하게 김선우의 주문 제품이 무엇인지
알아보려면 뷰를 만들기 이전에는 셀랙문에 서브쿼리를 이용하든 조인을 이용해서 제품테이블과 주문테이블을 연결 해주어야 하지만 전부 묶어서 뷰를 만들어 놓으면 셀렉문을 쓸때 from에 뷰를 걸어놓고 where 절에 김선우 라는 조건을 걸어만 주면 된다. 앙 기모륑~
-- 주문, 상품, 고객테이블을 조인하고
-- 판매데이터라는 뷰를 만드세요
-- 또한, banana 고객이 주문한 상품이름을 조회하세요
create view 판매데이터 as
select * from orderTest ot join productTest pt using(pdNum)
join customerTest ct using(csid);
select pdName from 판매데이터 where csid='banana';