테이블 백업을 수행하는 프로시저를 생성해보려고 한다.

기존 테이블(직원, 휴가, 휴가기록)에서 백업 테이블을 새로 생성하는 프로시저를 만든다.

프로시저를 생성하고 이벤트 스케쥴(event schedule)까지 걸어보겠다.



1. MySQL 프로시저 생성하기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DELIMITER $$
DROP PROCEDURE  IF EXISTS backup_proc;
 
CREATE PROCEDURE backup_proc()
 
BEGIN
    DROP TABLE IF EXISTS BACKUP_EMP;
    CREATE TABLE BACKUP_EMP SELECT * FROM EMP_EMPLOYEE;
    
    DROP TABLE IF EXISTS BACKUP_VAC;
    CREATE TABLE BACKUP_VAC SELECT * FROM VAC_VACATION;
    
    DROP TABLE IF EXISTS BACKUP_VAC_HIS;
    CREATE TABLE BACKUP_VAC_HIS SELECT * FROM VAC_HISTORY;
    
    SELECT '테이블 백업 성공';
END $$
 
DELIMITER ;
cs


백업테이블이 존재한다면 드랍하고 다시 생성할 것이고

없다면 백업테이블을 기존테이블에서 새로 생성한다는 간단한 쿼리이다.


프로시저를 저장했다면 프로시저를 호출해보자.



2. 프로시저 호출하기


1
CALL backup_proc();
cs





프로시저가 성공적으로 실행됐다면 select 구문에서 설정한 '테이블 백업 성공' 이라는 결과값이 나오고

BACKUP 테이블이 3개 생성된 것을 확인 할 수 있다.


3. 이벤트 스케쥴러 사용하기


매번 프로시저를 call해서 backup 테이블을 만들수는 없는 것이다.

이벤트 스케쥴러에 등록하여 DAY, MONTH, TIME 별로 시간을 지정해 준다면 자동으로 이벤트가 실행될 것이다.



- 이벤트 스케쥴러 ON


1
2
SHOW VARIABLES LIKE 'event%';
SET GLOBAL event_scheduler = ON ;
cs



- 이벤트 만들기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 매일 반복해서 실행
CREATE EVENT everyDayEvent1
    ON SCHEDULE 
 EVERY 1 DAY
STARTS '2019-07-30 00:00:00'
    DO CALL backup_proc();
 
-- 1달마다 반복해서 실행
CREATE EVENT everyMonthEvent1
    ON SCHEDULE 
 EVERY 1 MONTH
STARTS '2019-07-30 00:00:00'
    DO CALL backup_proc();
 
-- 1년마다 반복해서 실행
CREATE EVENT everyYearEvent1
    ON SCHEDULE 
 EVERY 1 YEAR
STARTS '2019-01-01 00:00:00'
    DO CALL backup_proc();
cs


이벤트를 만들고 스케쥴을 걸어 프로시저를 실행하는 구문이다.

이벤트를 생성하면 현재 등록된 이벤트의 목록을 확인해야 한다.



- 등록된 이벤트 조회하기


1
SELECT * FROM information_schema.`EVENTS` ;
cs


- 이벤트 삭제하기


1
2
3
DROP EVENT IF EXISTS everyDayEvent1;
DROP EVENT IF EXISTS everyMonthEvent1;
DROP EVENT IF EXISTS everyYearEvent1;
cs


백업 테이블명에 백업날짜를 붙여만들거나 

백업 테이블명을 각각 다르게하여 각각 스케쥴링을 걸어놓아 

백업을 정기적으로 할 수 있을 것 같다.




1. MySQL 설치를 완료한다.


최초 설치 시 root계정으로 비밀번호 설정을 하게 될 것이고

MySQL WorkBench로 root계정으로 로그인 되는지 테스트한다.



MySQL WorkBench로 들어와 test라는 스키마를 만든다.




2. IntelliJ 에서 build.gradle파일과 application.properties 파일을 수정한다.




build.gradle파일의 dependencies를 다음과 같이 작성한다.


1
2
3
4
5
6
7
dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('mysql:mysql-connector-java')
    compile('org.projectlombok:lombok')
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
cs


application.properties의 파일은 다음과 같이 작성한다.


1
2
3
4
5
6
7
8
9
10
11
# db url
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
 
# db name
spring.datasource.username=root
 
# db password
spring.datasource.password=0000
 
# query print
spring.jpa.show-sql=true
cs


아까전에 MySQL WorkBench로 테스트한 root 계정과 비밀번호를 넣어주고 

DB접속정보 포트(3306)와 연결할 스키마명(test)을 넣어준다.


만약 Illegal char <:>  mysql:mysql-con과 같은 오류가 발생하면 build > build project를 시도해본다.


아래와 같이 프로젝트를 실행시켰을 때 오류가 나지 않는다면 성공이다.





우리가 객체를 만들때 변수를 선언하고 기본생성자부터 Getter, Setter까지 메소드를 다 작성해줘야 하지만

Lombok 플러그인은 기본생성자부터, Getter, Setter 생성을 한번에 해결해준다.

개발자는 객체에 사용될 변수만 선언해주고 클래스명 위에 @Data라는 어노테이션만 선언해주면 된다.


1. File -> Settings 로 진입한다.




2. Plugins > Marketplace > lombok 검색한다.



install 버튼을 누르고 설치를 진행하고 intellij를 restart한다.


3. 설치가 완료되면 build.gradle의 dependencies를 수정한다.


 


1
2
3
4
5
6
dependencies {
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
cs




build.gradle 마우스 오른쪽 버튼 > Import Gradle Project 선택



build.gradle 에서 dependencies 부분 Run build, Rebuild 한다.



4. 모델로 돌아와 @Data를 선언해주고 lombok을 import한다.


1
2
3
4
5
6
7
8
9
10
package com.example.test.model;
 
import lombok.Data;
 
@Data
public class SearchVO {
    private String id;
    private String email;
    private int page;
}
cs


Structure를 보면 생성자, 메소드가 정의된 것을 확인 할 수 있다.



5. File -> Settings -> Annotation Processors 로 진입한다.



Enable annotation processing을 체크해준다.

컴파일이 오류없이 잘 되는지 확인한다.


lombok 설치 및 설정이 잘 된 것을 확인했다.


1. POST Method 만들기



controller 패키지에 PostAPIController.java를 생성해준다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.test.controller;
 
import com.example.test.model.SearchVO;
import org.springframework.web.bind.annotation.*;
 
@RestController
@RequestMapping("/api")
public class PostAPIController {
 
    // http통신할때 post는 body에다 data를 집어넣어서 받아오겠다.
    // @RequestBody에 SearchVO에 있는 값을 매칭해서 보내줘라.
    
    @RequestMapping(method = RequestMethod.POST, path = "/postRequest")
    public SearchVO postRequest(@RequestBody SearchVO searchVo){
        return searchVo;
    }
 
    @PostMapping(value = "/postMapping")
    public SearchVO postMapping(@RequestBody SearchVO searchVo){
        return searchVo;
    }
 
}
cs


위와 같이 POST 메소드를 작성한다.


GET 메소드와는 다르게 POST 메소드는 @RequestBody 어노테이션을 사용한다.

프론트에서 http 통신 시 post 메소드는 data를 body안에 담아서 가져온다.

body에 담아올때 메소드에 진입하면 모델이 가지고 있는 data만 json형태로 받아온다.


2. 테스트 해보기


크롬 웹스토어로 가서 REST API 확장 프로그램을 설치한다.

https://chrome.google.com/webstore/category/extensions?hl=ko



설치가 완료되면 POST 메소드로 json형태의 BODY를 작성하여 Send한다.



Response 200 으로 정상적으로 POST 된 것을 확인했다.



모델(SearchVO)에 있는 data만 json형태로 가져온것을 확인 할 수 있다.

모델에 존재하지 않은 param값을 프론트에서 보내면 @RequestBody에서 받아오지 못한다.


POST 메소드 구현 및 테스트를 완료했다.


REST API 구현하기


HTTP Method GET


1. GET 메소드 구현하기



com.example.test 아래에 controller 패키지를 생성하고 GetAPIController.java 파일을 생성한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.test.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
@RestController // 여기는 컨트롤러라고 알려주는 @RestController 어노테이션 사용
@RequestMapping("/api"// 여기로 들어올 path를 지정할 @RequestMapping 어노테이션 사용 localhost:8080/api
public class GetAPIController {
 
    @RequestMapping(method = RequestMethod.GET, path = "/getRequest")   // localhost:8080/api/getRequest
    public String getRequest(){
        return "this is getRequest";
    }
 
}
cs


GetAPIController.java 의 내용을 위와 같이 넣어준다.

그리고 웹브라우저를 통해 http://localhost:8080/api/getRequest로 접속하여 결과가 나오는지 테스트한다.




결과가 잘 나오는 것을 확인했다.


하지만 GET Method는 웹에서 파라미터가 뒤에 계속 붙으면서 보여진다.

이런식으로 http://localhost:8080/api/getRequest?id=shlee0882&email=shlee0882@gmail.com

요청해야하는데 파라미터를 받아서 처리해보자.


2. 파라미터 받아서 GET 메소드 처리하기


1
2
3
4
5
    // GetMapping은 RequestMapping과는 다르게 메소드유형 없이 주소만 지정해주면된다.
    @GetMapping("/getParameters")  // localhost:8080/api/getParameters?id=shlee0882&email=shlee0882@gmail.com
    public String getParameters(@RequestParam String id, @RequestParam String email){
        return "아이디는 "+id+" 이메일은 "+email;
    }
cs


@GetMapping이라는 어노테이션을 사용했다.

@GetMapping은 @RequestMapping과 다르게 메소드유형 없이 path만 지정해 주면 된다.

메소드로 받을 인자값 2개를 설정해 주었다.

웹브라우저를 통해 파람값을 붙여서 요청했다.

http://localhost:8080/api/getRequest?id=shlee0882&email=shlee0882@gmail.com

결과가 잘 나오는 것을 확인했다.



위의 메소드는 인자값이 Request 파라미터값이 되기 때문에

메소드의 인자값을 바꿔주고 싶을때는 RequestParam의 name을 지정해주고 

받아온 param값의 변수를 새롭게 지정하여 활용할 수 있다.


1
2
3
4
5
    @GetMapping("/getParameters")  
    public String getParameters(@RequestParam(name = "id"String userId
                              , @RequestParam(name = "email"String userEmail){
        return "아이디는 "+userId+" 이메일은 "+userEmail;
    }
cs


하지만 만약 프론트에서 넘어온 데이터 RequestParam값이 10개 이상이면 

매번 RequestParam을 선언해주며 인자를 만들수는 없다.


이럴경우 모델(Model) 객체를 활용하여 받아올수 있다.



model 패키지를 생성하여 SearchVO.java를 만든다.


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
package com.example.test.model;
 
public class SearchVO {
    private String id;
    private String email;
    private int page;
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getEmail() {
        return email;
    }
 
    public void setEmail(String email) {
        this.email = email;
    }
 
    public int getPage() {
        return page;
    }
 
    public void setPage(int page) {
        this.page = page;
    }
}
cs


SearchVO.java의 Getter, Setter 메소드 모델을 작성해준다.


1
2
3
4
    @GetMapping("/getMultiParameters")
    public String getMultiParameters(SearchVO searchVo) {
        return "VO사용 아이디는 "+searchVo.getId()+" 이메일은 "+searchVo.getEmail();
    }
cs


http://localhost:8080/api/getMultiParameters?id=shlee0882&email=shlee0882@gmail.com 요청한다.



객체를 사용하여 인자 1개만으로 여러개의 파라미터를 받아 처리하여 결과가 잘 나온것 확인했다.


하지만 API는 대부분 요청에 대한 응답 결과값을 json형태로 받는다.

결과값을 json 형태 { id : shlee0882, email : shlee0882@gmail.com } 이런식으로 return 받으려면 다음과 같이 작성할 수 있다. 


1
2
3
4
    @GetMapping("/getMultiParametersRtnJson")
    public SearchVO getMultiParametersRtnJson(SearchVO searchVo) {
        return searchVo;
    }
cs


http://localhost:8080/api/getMultiParametersRtnJson?id=shlee0882&email=shlee0882@gmail.com 요청한다.



결과가 json으로 받아지는 것을 확인했다.


Spring Boot 프로젝트 만들기 - 1


1. IntelliJ에서 프로젝트 생성하기


- JDK 12 설치


인텔리J를 사용하려면 높은 JDK버전이 필요하므로 JDK 12를 설치한다.


https://www.oracle.com/technetwork/java/javase/downloads/jdk12-downloads-5295953.html



- Intellij 설치




https://www.jetbrains.com/idea/download/#section=windows


인텔리J IDEA Ultimate 버전을 다운받는다.

평가판으로 일정기간 무료로 사용할수 있다.




위와 같이 체크해준다.

64비트, Update Path variable, 

Add "Open Folder as Project", .java, Download install JBR x86 (젯브레인에서 제공하는 라이브러리도 설치) 한다.


설치가 완료되면 바탕화면에 바로가기 아이콘이 생성되고 intellij를 실행한다.



기본설정을 선택하고 OK버튼을 누른다.



본인이 원하는 테마를 선택하고 다음 설정으로 넘어간다.



커스터마이징 하는부분인데 기본설정으로 다음으로 넘어간다.



다음버튼을 누른다.



30일 평가판으로 설치한다.



설치가 완료되면 다음과 같이 나타난다.

Create New Project를 누른다.



Project SDK가 JDK 12로 잡혀져있는지 확인한다.

왼쪽 메뉴에 Spring Initializer를 선택하고 Next를 누른다.



이름은 test로 Gradle Project를 선택하고 기본셋팅으로 Next를 누른다.



새 프로젝트를 어떻게 구성할지 체크해서 시작할수 있다.

간단하게 Web > Spring Web Starter를 체크하여 Next 버튼을 누른다.



Finsh 버튼을 누른다.



그러면 다음과 같이 import Module from Gradle 이라는 창이 뜨고

Use auto-import, Use default Gradle wrapper를 선택해주고 OK버튼을 누른다.



sync가 finished 되면 프로젝트를 실행시켜본다. 

Shift+F10 단축키나 TestApplication.java 파일로 접근하여 실행버튼을 누르면 된다.



Tomcat started on port 8080이 나타나면 성공이다.

Spring Boot 개발환경 설정을 완료했다.



2. Spring Initializer 활용하여 생성하기


https://start.spring.io/ 로 접속한다.



Dependencies에서 필요한 것들을 추가한 다음

Generate the project로 생성한다.


zip파일로 다운 되는데 압축을 푼다.


intelliJ를 실행하여 File > Open 으로 압축푼 폴더를 지정한다.




Use-auto-import를 체크해주고 OK 버튼을 누른다.




생성이 완료 되고 프로젝트를 실행하면 잘 구동되는 것을 확인 했다.


쿼리에서 조건을 걸어 데이터가 return 0 row일때

쿼리에서 "값이 없다" 라는 결과를 리턴값으로 처리하는 방법을 사용해보려한다.


1. 테이블 생성하기


1
2
3
4
5
6
CREATE TABLE `CODE_TABLE` (
    `CODE_CD` VARCHAR(10NOT NULL COLLATE 'utf8_bin',
    `CODE_NM` VARCHAR(10NOT NULL COLLATE 'utf8_bin'
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB;
cs


코드테이블이라는 테스트 테이블을 생성한다.

코드테이블은 코드, 코드명 컬럼으로 구성된다.


2. 데이터 넣기


1
2
3
4
5
INSERT INTO CODE_TABLE VALUES('10','개발팀');
 
INSERT INTO CODE_TABLE VALUES('20','영업팀');
 
INSERT INTO CODE_TABLE VALUES('30','기획팀');
cs


기초데이터를 넣어준다.



3. 없는 데이터 조회하기


1
2
3
4
-- SELECT한 Row가 0이므로 IFNULL 처리 불가        
SELECT IFNULL(A.CODE_NM, '없는 코드') AS CODE_NM
  FROM CODE_TABLE A
 WHERE A.CODE_CD = '100';
cs


현재 CODE_CD컬럼의 데이터는 10,20,30 이 들어가 있고

where절에서 '100' 을 조회하면 데이터가 조회되지 않는다.


위와 같이 쿼리를 작성하면 데이터가 있다면 코드명이 나오고

데이터가 없다면 아무것도 나오지 않는다.


SELECT 한 결과가 0건이라도

IFNULL에 걸린 것 처럼 "없는 코드" 라고 결과가 나오게 하고 싶다.



4. DUAL 테이블과 외부조인 걸기


1
2
3
4
     SELECT IFNULL(A.CODE_NM, '없는 코드') AS CODE_NM
       FROM CODE_TABLE A 
RIGHT OUTER JOIN (SELECT '') AS m_dual
         ON A.CODE_CD = '100';
cs



DUAL을 외부조인으로 사용하여 CODE가 없다면 "없는코드", 있다면 코드명이 나온다.


5. 집계함수 사용하기


1
2
3
     SELECT IFNULL(MAX(A.CODE_NM), '없는 코드') AS CODE_NM
       FROM CODE_TABLE A 
      WHERE A.CODE_CD = '100';
cs



집계함수를 사용하여 CODE가 없다면 "없는코드", 있다면 코드명이 나온다.


프로시저나 함수를 작성할때 

결과값이 없더라도 MESSAGE로 출력하고 싶다면 유용하게 쓰일수 있을 것 같다.


MySQL function을 이용해 직원 출석등록 함수를 만들어보겠다.


1. 테이블 생성하기


1
2
3
4
5
6
7
CREATE TABLE `EMP_ATTEND` (
    `ATTEND_YMD` VARCHAR(8NOT NULL COLLATE 'utf8_bin',
    `EMP_NO` VARCHAR(9NOT NULL COLLATE 'utf8_bin'
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB;
 
cs


간단하게 직원출석 테이블을 생성한다.



2. 함수 생성하기


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
32
33
34
35
DELIMITER $$
 
DROP FUNCTION IF EXISTS FNC_ATTEND;
 
CREATE FUNCTION FNC_ATTEND(attendType VARCHAR(10), empNo VARCHAR(10)) RETURNS BOOL
 
BEGIN
     DECLARE exist_flag INT;
     DECLARE returnVal  BOOL;
         SET returnVal = FALSE;
 
     -- 출석 등록
     IF 'attend'= attendType THEN
         SELECT COUNT(1)
           INTO exist_flag
           FROM EMP_ATTEND
          WHERE EMP_NO = empNo 
            AND ATTEND_YMD = DATE_FORMAT(NOW(), '%Y%m%d')
         ;
         
         IF exist_flag = 0 THEN
             INSERT INTO EMP_ATTEND(
                      ATTEND_YMD
                    , EMP_NO
             )VALUES(
                   DATE_FORMAT(NOW(), '%Y%m%d')
                     , empNo 
             );
             SET returnVal = TRUE;
         END IF;
     END IF;
      RETURN returnVal;
END $$
 
DELIMITER ;
cs


function의 argument 2개를 지정해 생성하고 return 값은 boolean으로 받겠다.


만약 arg로 들어온 첫번째 값이  문자열 'attend' 일경우 

테이블에 해당 직원의 오늘날짜로 출석한 데이터가 있는지 확인하고

데이터가 없다면 오늘날짜와 직원번호로 값을 insert한다.


값이 insert 된 후 returnVal의 값은 TRUE가 된다.



3. 함수 호출하기


1
2
3
4
-- if return value 0 then false
-- else if return value 1 then true
 
SELECT FNC_ATTEND('attend''1000');
cs



함수를 생성하고 위와 같이 호출을 해본다.


2개 파람값을 넣고 호출하면 1이나 0이 나오게 된다.

0이 나오면 false, 1이 나오면 true이다.

 


4. 테이블 조회하기


1
SELECT * FROM EMP_ATTEND;
cs


직원출석 테이블을 조회하면 값이 잘 들어간 것을 확인할 수 있다.



EMP_NO 하나당 하루에 한번 출석등록을 할 수 있는 function을 만들어보았다.

+ Recent posts