1. UPDATE ''(공백), NULL 이후 SELECT 하기


1
2
3
4
5
6
/* 테스트 테이블 생성 */
CREATE TABLE TEST_TABLE1 AS(
    SELECT 1 E_ID, '조현영' E_NAME FROM DUAL UNION ALL
    SELECT 2 E_ID, '이상현' E_NAME FROM DUAL UNION ALL
    SELECT 3 E_ID, '김지숙' E_NAME FROM DUAL 
);
cs


1
2
3
/* 조회하기 */
SELECT * 
  FROM TEST_TABLE1;
cs




1
2
3
4
/* E_NAME을 공백으로 업데이트 한다. */
UPDATE TEST_TABLE1
   SET E_NAME = ''
 WHERE E_ID = 1;
cs


1
2
3
4
/* E_NAME을 공백으로 업데이트 한 내용을 SELECT한다. */
SELECT * 
  FROM TEST_TABLE1
 WHERE E_NAME = '';
cs




결과가 나오지 않는다.


본인은 E_NAME을 공백으로 UPDATE를 완료하고 

E_NAME에는 공백의 데이터가 들어갈 것이라 예상했지만 

공백으로 조회했을때 데이터가 조회되지 않는다.


1
2
3
4
/*결과가 나온다. */
SELECT * 
  FROM TEST_TABLE1
 WHERE E_NAME IS NULL;
cs


하지만 IS NULL로 SELECT를 하면 데이터가 조회된다.



이 결과를 통해 NULL, 공백('') 모두 NULL로 업데이트 치는 것을 확인했다.


1
2
3
4
5
6
7
8
9
/* E_NAME을 공백으로 업데이트 한다. */
UPDATE TEST_TABLE1
   SET E_NAME = ''
 WHERE E_ID = 1;
 
/* E_NAME은 NULL로 업데이트 된다. */
UPDATE TEST_TABLE1
   SET E_NAME = NULL
 WHERE E_ID = 1;
cs


Mybatis를 사용한다면 param값의 유무에 따라 null과 공백을 같이 체크하는 경우를

다음과 같이 볼 수 있다. 


1
2
<if test='custNo != null and custNo != ""'>
</if>
cs


본인은 쿼리에서도 공백으로 데이터를 넣으면 공백으로 업데이트 되는 줄 알았던 것이다.




2. 테이블 컬럼 데이터 쉽게 UPDATE 하는 방법 


일반적인 UPDATE 문이다.

1
2
3
UPDATE TEST_TABLE1
   SET E_NAME = ''
 WHERE E_ID = 1;
cs


UPDATE 하기전 UPDATE할 데이터를 미리 SELECT 하고 데이터를 확인해

조건을 걸어 작업 하는 경우가 많은데 2단계의 과정 대신

SELECT 해서 바로 컬럼으로 접근해 고칠수 있는 방법이 있다.


1
2
3
4
5
6
7
 EDIT [테이블명] 
 WHERE [컬럼] = [조건]
 ;
 
 SELECT A.*, ROWID
   FROM [테이블명] alias A
 ;
cs


위 구문을 사용하면 SELECT하고 해당 컬럼 데이터에 마우스 더블클릭으로 데이터를 조작하여 업데이트 할 수 있다.







JSONObject로 생성, JSONObject 리스트 JSONArray에 넣기, JSONArray를 ArrayList에 넣기



1. string 형태의 배열문자열을 split 하여 string array에 넣는다. 


1
2
String[] myCodeArr = [01020304]
String[] motherCodeArr = [999897]
cs



2. string array에 들어간 데이터 값과 name, updateTime값을 JSONObject에 다시 넣는다.


1
2
3
4
5
6
JSONObject jsonObj1 = new JSONObject();

jsonObj1.put("myCode", myCodeArr);
jsonObj1.put("name", name);
jsonObj1.put("motherCode", motherCodeArr);
jsonObj1.put("updatedTime", updatedTime);
cs


1
2
3
4
5
6
  "myCode":["01","02","03","04"],
  "name":"jihyun",
  "motherCode":["99","98","97"],
  "updatedTime":"2019-11-05 12:48:12"
}
cs



3. JSONObject를 여러개 갖고 싶어 JSONArray 안에 다시 넣는다.


1
2
JSONArray jsonArr1 = new JSONArray();
jsonArr1.put(jsonObj1);
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
   { 
      "myCode":["01","02","03","04"],
      "name":"jihyun",
      "motherCode":["99","98","97"],
      "updatedTime":"2019-11-05 12:48:12"
   },
   { 
      "myCode":["11","22","33"],
      "name":"yumi",
      "motherCode":["20","30"],
      "updatedTime":"2019-11-05 12:48:12"
   }
]
cs



4. JSONArray에 담긴 것을 JSONObject 형식을 유지한 ArrayList로 만들고 싶다.

JSONArray에 담긴 것을 하나씩 JSONObject로 뽑아내어 ArrayList에 add 시킨다.

JSONObject[] jsons안에 array사이즈를 할당하고 toArray() 를 사용해 arrayJson이 갖고 있는 값의 형태로 arraylist를 생성한다.


1
2
3
4
5
6
7
8
9
ArrayList<JSONObject> arrayJson = new ArrayList<JSONObject>();
 
for (int k = 0; k < jsonArr1.length(); k++) {
    JSONObject tempJson = jsonArr1.getJSONObject(k);
    arrayJson.add(tempJson);
}
 
JSONObject[] jsons = new JSONObject[arrayJson.size()];
arrayJson.toArray(jsons);
cs



5. 전체 소스


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
36
37
38
39
40
41
42
43
private void arrIntoJson() throws JSONException {
 
    String name = "";
    String myCode = "";
    String motherCode = "";
    JSONArray jsonArr1 = new JSONArray();
    
    for(int i=0; i<2; i++) {
    
        if(i==0) {
            name = "jihyun";
            myCode = "[01,02,03,04]";
            motherCode = "[99,98,97]";
        }else {
            name = "yumi";
            myCode = "[11,22,33]";
            motherCode = "[20,30]";
        }
        
        String updatedTime = String.valueOf(DateUtil.getLocalDateTime("yyyy-MM-dd HH:mm:ss"));
        String[] myCodeArr = myCode.substring(1, myCode.length()-1).split(",");
        String[] motherCodeArr = motherCode.substring(1, motherCode.length()-1).split(",");
        
        JSONObject jsonObj1 = new JSONObject();
        jsonObj1.put("name", name);
        jsonObj1.put("myCode", myCodeArr);
        jsonObj1.put("motherCode", motherCodeArr);
        jsonObj1.put("updatedTime", updatedTime);
        jsonArr1.put(jsonObj1);
    }
    
    ArrayList<JSONObject> arrayJson = new ArrayList<JSONObject>();
    
    for (int k = 0; k < jsonArr1.length(); k++) {
        JSONObject tempJson = jsonArr1.getJSONObject(k);
        arrayJson.add(tempJson);
    }
    
    JSONObject[] jsons = new JSONObject[arrayJson.size()];
    arrayJson.toArray(jsons);
    
    System.out.println(jsons);
}
cs


arrayJson의 값


1
2
3
4
5
6
7
8
9
10
11
12
13
14
   { 
      "myCode":["01","02","03","04"],
      "name":"jihyun",
      "motherCode":["99","98","97"],
      "updatedTime":"2019-11-05 12:48:12"
   },
   { 
      "myCode":["11","22","33"],
      "name":"yumi",
      "motherCode":["20","30"],
      "updatedTime":"2019-11-05 12:48:12"
   }
]
cs



사실 IaaS, PaaS, SaaS 를 소프트웨어 공학 시간에 배운적이 있지만

실제로 사용해보기 전까진 잘 알지 못했다. 


개념은 이해 되는데 실제 개발 및 테스트를 위해 사용해보고 

개념을 다시 살펴봤는데 본인이 사용한 서비스가 어떤 서비스였는지 잘 확인 할 수 있었다.





1. IaaS


서비스로서의 인프라스트럭처(Infrastructure as a Service, IaaS)는 서버, 스토리지, 네트워크를 필요에 따라 인프라 자원을 사용할 수 있게 클라우드 서비스를 제공하는 형태이다. 


간략하게 IaaS는 컴퓨터만 할당 받는것이다.


너가 만약 웹개발을 하여 만든 소스를 올리고 싶다면 


OS : 리눅스(16.x,18.x) 윈도우(7,10) 선택

Web Server : 톰캣(8.x,9.x), 웹로직, etc 선택

DB : mysql, mssql, maria, etc 선택 


버전까지 선택하여 개발환경을 꾸릴수 있다.

선택권이 모두 개발자에게 넘어간 것이다. 컴퓨터 환경만 빌려서 사용한다.


대표적인 서비스로




AWS EC2, Google Cloud Platform, Azure Virtual Machines, Naver Cloud Platform 이 있다.


위 서비스들은 1년간 무료사용 서비스를 제공한다.


초보 개발자들이나 돈이 없는 개발자들은 각각 1년간 IaaS를 돌려쓰며 돈을 아껴보자.

본인도 개발 및 간단한 테스트를 위해 1년간 돌려가며 써볼 생각이다. 

현재 1년간 무료 AWS EC2 서비스를 사용중인데 매우 만족하며 쓰고 있다.



2. PaaS


PaaS (Platform as a Service)라고도하는 클라우드 플랫폼 서비스는 

주로 애플리케이션에 사용되는 동안 특정 소프트웨어에 클라우드 구성 요소를 제공한다. 

PaaS는 개발자가 맞춤형 애플리케이션을 개발하고 구축 할 수있는 프레임 워크를 제공한다. 

모든 서버, 스토리지 및 네트워킹은 엔터프라이즈 또는 타사 공급자가 관리 할 수 ​​있으며 개발자는 응용 프로그램 관리를 유지할 수 있다.


간략하게 PaaS는 플랫폼서비스로


개발자는 IaaS에서 했던 복잡한 설치 및 환경설정을 하지 않아도 된다.

PaaS에서 정해준 OS, 버전, 어플리케이션 등이 있으므로 개발자는 완성된 소스를 올리기만 하면 된다.


개발자의 선택권이 줄어들었지만 그만큼 플랫폼에게 권한을 위임함으로써 

복잡한 서버, 환경구성에 신경쓰지 않아도 된다.


당연히 IaaS보다 PaaS가 비용면에서 비싸다.




AWS Elastic Beanstalk, Windows Azure, Heroku 등이 있다.


본인은 NodeJS소스를 Heroku에 바로 올려보았는데 정말 소스만 올리면 바로 올라가는 것을 확인 할 수 있었다.



3. SaaS


서비스로서의 소프트웨어(Software as a Service, SaaS)는 소프트웨어 및 관련 데이터는 중앙에 호스팅되고 사용자는 웹 브라우저 등의 클라이언트를 통해 접속하는 형태의 소프트웨어 전달 모델이다. 주문형 소프트웨어(on-demand software, 온디맨드 소프트웨어)라고도 한다.


간략하게 서비스를 이용할 수 있는 소프트웨어를 말한다.




Google Apps, Mail, Youtube, Blog ... 등이 있다.


1. 자바스크립트 이용한 pc, 모바일 체크, DOMContentLoaded 이벤트 사용하기


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
36
37
38
39
40
41
42
43
<script type="text/javascript">
 
var onresize = function() {
    var width = document.body.clientWidth;
    var height = document.body.clientHeight;
    if(width <= 1575){
        smallMenu();
    }else{
        largeMenu();
    }
};
 
var top_frame01 = document.getElementById('top_frame01');
    
var smallMenu = function(){
    top_frame01.setAttribute( 'rows''120,*' )
};
 
var largeMenu = function(){
    top_frame01.setAttribute( 'rows''90,*' )
};
 
// 모바일, pc 체크
window.mobilecheck = function() {
      var check = false;
      (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m||s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
      return check;
};
 
// DOMContentLoaded
window.addEventListener('DOMContentLoaded'function(){
    if(mobilecheck()){
        console.log('mobile');
        smallMenu();
    }else{
        console.log('pc');
        largeMenu();
    }
});
 
window.addEventListener("resize"onresize);
 
</script>
cs


index.jsp가 화면에 로딩될때 접근한 기기가 PC인지 모바일인지 확인 후 상단의 메뉴 사이즈를 줄여주려고 한다.


처음에 windows.onload = function(){} 을 사용했으나 모든 콘텐츠가 로드된 후 실행되어 스크립트가 늦게 실행되어 화면이 늦게 바뀌는 문제점이 있었다.


그래서 DOMContentLoaded 이벤트를 사용했다.  

DOMContentLoaded는 최초 HTML 문서가 완전히 로드 및 파싱되었을때 발생되고, 

스타일시트나 이미지 및 서브프레임 로드가 끝나기를 기다리지 않는다고 한다.


$(document).ready(function(){}); 은 jquery에서 쓰는 것인데 DOMContentLoaded 이벤트와 동일하다.



1. 프로젝트 구조 생성



- model 하위에 entity package를 생성하고 User 클래스를 만든다.

- repository package를 생성하고 하위에 UserRepository 인터페이스를 생성한다.

- test 패키지 하위에 repository package아래에 UserRepositoryTest라는 test클래스를 만든다.



2. user 테이블 생성


1
2
3
4
5
6
7
8
9
10
CREATE TABLE `test`.`user` (
  `id` BIGINT(20NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45NULL,
  `email` VARCHAR(45NULL DEFAULT NULL,
  `phone_number` VARCHAR(45NULL DEFAULT NULL,
  `reg_dt` VARCHAR(45NOT NULL,
  `reg_user` VARCHAR(45NOT NULL,
  `mod_dt` VARCHAR(45NULL DEFAULT NULL,
  `mod_user` VARCHAR(45NULL DEFAULT NULL,
  PRIMARY KEY (`id`));
cs


MySQL Tool (workbench, heidiSQL) 을 통해 test 데이터베이스에 user테이블을 생성한다.

생성할때 컬럼은 snake_case를 사용하여 각 단어와 단어 사이에  _언더바로 표시한다.



3. User 모델 생성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.test.model.entity;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDateTime;
 
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    private String phoneNumber;
    private LocalDateTime regDt;
    private String regUser;
    private LocalDateTime modDt;
    private String modUser;
}
cs



자바에선 user테이블의 컬럼명에 맞춰 

camel case를 사용하여 모델 User클래스를 만든다.



4. UserRepository 인터페이스 생성


1
2
3
4
5
6
7
8
9
10
package com.example.test.repository;
 
import com.example.test.model.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
 
@Repository
public interface UserRepository extends JpaRepository<User,Long> {
 
}
cs


JpaRepository를 상속받아 생성한다.



5. UserRepositoryTest 클래스 생성


5.1 create


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
package com.example.test.repository;
 
import com.example.test.TestApplicationTests;
import com.example.test.model.entity.User;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
 
import java.time.LocalDateTime;
 
public class UserRepositoryTest extends TestApplicationTests {
 
    @Autowired
    private UserRepository userRepository;
 
    @Test
    public void create(){
        User user = new User();
        user.setName("user1");
        user.setEmail("user1@gmail.com");
        user.setPhoneNumber("010-1111-2222");
        user.setRegDt(LocalDateTime.now());
        user.setRegUser("shlee0882");
 
        User newUser = userRepository.save(user);
        System.out.println(newUser);
    }
}
 
cs


User 모델을 객체로 가져와 값을 set하고 

DI (의존성주입)를 사용해 UserRepository로 만든 객체에 save한다.


Test를 실행하면 데이터가 잘 들어간것을 확인할 수 있다.




5.2 read


1
2
3
4
5
6
7
8
    @Test
    public void read(){
        Optional<User> user = userRepository.findById(1L);
 
        user.ifPresent(selectUser ->{
            System.out.println("user: "+selectUser);
        });
    }
cs


read 메소드를 run하면 

id는 모델에서 long으로 선언 되어 있으므로 L을 붙여 id가 1번인 데이터를 찾는다.

데이터를 찾아 user객체에 담아주고 출력한다.


출력결과


1
user: User(id=1, name=user1, email=user1@gmail.com, phoneNumber=010-1111-2222, regDt=2019-08-09T09:25:28.653, regUser=shlee0882, modDt=2019-08-09T09:27:51.381, modUser=shlee0882)
cs


5.3 update


1
2
3
4
5
6
7
8
9
10
11
12
13
    @Test
    public void update(){
        Optional<User> user = userRepository.findById(1L);
 
        user.ifPresent(selectUser ->{
            selectUser.setUserAccount("modUser1");
            selectUser.setEmail("modUser1@gmail.com");
            selectUser.setModDt(LocalDateTime.now());
            selectUser.setModUser("shlee0882");
            User newUser = userRepository.save(selectUser);
            System.out.println("user: "+newUser);
        });
    }
cs


update 메소드를 run하면

id가 1번인 데이터를 찾아 user객체에 담고

담은 user의 객체의 값을 새로 set해주고 save하면 

기존의 데이터가 있다면 update가 일어난다.


출력결과


1
user: User(id=1, name=modUser1, email=modUser1@gmail.com, phoneNumber=010-1111-2222, regDt=2019-08-09T09:25:28.653, regUser=shlee0882, modDt=2019-08-09T11:20:17.179, modUser=shlee0882)
cs


5.4 delete


1
2
3
4
5
6
7
8
9
10
11
12
13
    @Test
    public void delete(){
        Optional<User> user = userRepository.findById(1L);
 
        Assert.assertTrue(user.isPresent());    // true
        user.ifPresent(selectUser ->{
            userRepository.delete(selectUser);
        });
 
        Optional<User> deleteUser = userRepository.findById(1L);
 
        Assert.assertFalse(deleteUser.isPresent());    // false
    }
cs


delete메소드는 id를 찾아 있다면 true, 

데이터 삭제 후 id가 있는지 확인 후 없다면 false를 통과한다.



5.5 Transactional



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
    @Test
    @Transactional
    public void update(){
        Optional<User> user = userRepository.findById(1L);
 
        user.ifPresent(selectUser ->{
            selectUser.setName("modUser1");
            selectUser.setEmail("modUser1@gmail.com");
            selectUser.setModDt(LocalDateTime.now());
            selectUser.setModUser("shlee0882");
            User newUser = userRepository.save(selectUser);
            System.out.println("user: "+newUser);
        });
    }
 
    @Test
    @Transactional
    public void delete(){
        Optional<User> user = userRepository.findById(1L);
 
        Assert.assertTrue(user.isPresent());    // true
        user.ifPresent(selectUser ->{
            userRepository.delete(selectUser);
        });
 
        Optional<User> deleteUser = userRepository.findById(1L);
 
        Assert.assertFalse(deleteUser.isPresent());    // false
    }
cs


transactional 어노테이션을 넣으면

update와 delete 시 RollBack 되는것을 확인할 수 있다. 


1
Rolled back transaction for test: [DefaultTestContext@576dad90 testClass = UserRepositoryTest, testInstance = com.example.test.repository.UserRepositoryTest@97bd416, testMethod = delete@UserRepositoryTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@5baaa549 testClass = UserRepositoryTest, locations = '{}', classes = '{class com.example.test.TestApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@7097fbf1, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7ed6156f, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@2c5d456b, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@6b04043b], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]
cs





평소 Notepad++를 많이 사용하는데 

여러개의 텍스트파일을 띄워두고 저장하지 않고

기록만 해두었다 필요한 내용을 정리하는 편이다.


Notepad++ 사용시 save 할지 말지 알림창이 뜨는경우가 있다. 




설정 > 기본설정 > 백업 > 세션 스냅샷 체크를 2개 해준다.





이제 여러 탭을 열어 텍스트를 작성하고

텍스트 저장없이 Notepad++를 껐다 켰다 할수 있다.



1. 유저 삭제하기


1
drop user [user명] cascade;
cs


[ORA-28014: cannot drop administrative users] 발생 시


1
alter session set "_oracle_script"=true;
cs



[ORA-01940: cannot drop a user that is currently connected] 발생 시


현재 session에 대해 select 하여 session을 KILL해줘야 한다.



- session 조회 하기

1
select sid,serial# from v$session where username = [user명 대문자로];
cs


- session KILL 하기

1
ALTER SYSTEM KILL SESSION '[SID], [SERIAL]';
cs


- use drop 하기

1
drop user dev_emart cascade;
cs



2. 유저 생성하기


1
2
3
4
5
6
7
8
9
alter session set "_ORACLE_SCRIPT"=true;
 
create user [user명] identified by [패스워드];
 
grant create session to [user명];
 
grant connect, resource to [user명];
 
alter user [user명] default tablespace users quota unlimited on users;
cs


그동안 단일 건이나 간단한 IF문만 사용하여

프로시저를 생성했는데 MySQL에서도 Oracle의 Cursor같이 여러개의 데이터를 뽑아와 

데이터를 반복하여 작업을 진행해보려한다.



1. TEST 테이블 생성하기


1
2
3
4
5
6
7
8
9
CREATE TABLE `TEST_TB1` (
    `id` BIGINT(20NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(50NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `useYn` VARCHAR(50NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=6;
cs



2. 기초 데이터 넣기


1
2
3
4
5
6
7
8
9
-- auto increment 초기화
ALTER TABLE TEST_TB1 AUTO_INCREMENT = 0;
 
-- 데이터 삽입
INSERT INTO TEST_TB1(name, useYn) VALUES('조현영''Y');
INSERT INTO TEST_TB1(name, useYn) VALUES('박초아''Y');
INSERT INTO TEST_TB1(name, useYn) VALUES('김태연''Y');
INSERT INTO TEST_TB1(name, useYn) VALUES('김지숙''Y');
INSERT INTO TEST_TB1(name, useYn) VALUES('이상현''Y');
cs


테이블 조회 결과 





3. 프로시저 만들기


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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
DELIMITER $$
DROP PROCEDURE  IF EXISTS test_proc1;
 
CREATE PROCEDURE test_proc1()
 
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE v_count INT DEFAULT -1;
  DECLARE v_id varchar(20);
  DECLARE v_name varchar(20);
  DECLARE v_useYn varchar(20);
    
  -- select한 결과를 cursor1로 정의 
  DECLARE cursor1 CURSOR FOR 
   SELECT id
         , name
         , useYn
     FROM TEST_TB1;
 
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
 
  OPEN cursor1;
 
  my_loop: LOOP
 
  -- loop 하며 cursor1의 데이터를 불러와 변수에 넣는다.
  FETCH cursor1 
   INTO v_id
        , v_name
        , v_useYn;
    
     SET v_count = v_count +1 ; 
 
    -- cursor1 반복이 끝나면 loop 빠져나간다.
    IF done THEN
      LEAVE my_loop;
    END IF;
     
     IF(v_id = 1) THEN
         UPDATE TEST_TB1
           SET name = '전효성'
         WHERE id = v_id;
 
    ELSEIF (v_id = 2) THEN
    INSERT INTO TEST_TB1(name, useYn)
         VALUES('insert값''N');
         
    ELSE 
         UPDATE TEST_TB1
           SET name = CONCAT(v_name, v_id)
         WHERE id = v_id;
         
     END IF;
     
  END LOOP;
 
  SELECT v_count; 
 
  -- 커서를 닫는다. 
  CLOSE cursor1;
 
END $$
 
DELIMITER ;
 
cs



cursor1에서 select한 데이터를 모두 갖고 있고

fetch를 통해 cursor의 데이터를 변수에 담고


변수에 담은 데이터를 하나씩 LOOP를 돌면서

IF문에 걸릴경우 UPDATE나 INSERT문을 만나

처리를 진행하게 된다.


LOOP를 돌릴때마다 변수의 count를 올리고 있다.



4. 프로시저 호출하기


1
CALL test_proc1();
cs



프로시저를 실행하게 되면 기존 데이터가 변경되고 신규 데이터가 추가된 것을 확인 할 수 있다.


+ Recent posts