1. 쿼리에서 select 한 값을 List(5만건)로 받아와서 foreach로 update 하기


foreach 방식일경우


1. 같은 행사번호에 10만원~20만원 사이 구매한 고객이 5만명이고 이 5만명이 각각 다른 응모자참여번호가 들어갈때

2. 응모자 5만명을 모두 당첨처리를 하기 위해선

3. 응모자참여번호 5만명을 SELECT 하여 Java에 List로 받아오고

4. List에 저장된 5만개의 응모자참여번호를 foreach를 통해 update를 5만번 실시함.

5. 같은 쿼리를 5만번이나 실행하니 비효율적이고 실행시간이 매우 오래걸리는 단점



1
2
3
4
5
//  1. 응모자참여번호 5만명을 SELECT 하여 Java에 List로 받아온다.
 
List<PrEvntTkpt> prEvntTkptList = commonEventsReadOnlyDAO.selectWinnerEvntTkptList( param);
 
//  prEvntTkptList에는 5만건의 데이터 가지고 있음.
cs


1
2
3
4
5
6
7
8
9
10
-- 2. 응모자 5만명을 모두 당첨처리를 하기 위해선
-- 5만명에 대한 각각의 응모자참여번호를 쿼리로 구해오고
-- <id= selectWinnerEvntTkptList>
 SELECT a.EVNT_PTCP_NO -- 이벤트 참여 번호
   FROM pr_evnt_ptcp_ord a -- 응모참여 주문테이블
  WHERE a.CMPN_NO = '1'
  GROUP BY a.EVNT_PTCP_NO, a.CMPN_NO
 HAVING SUM(a.PUR_RCGN_AMT) >= 100000
    AND SUM(a.PUR_RCGN_AMT) < 200000 
-- result return rows  50000
cs


1
2
3
4
5
6
7
8
9
10
11
// 3. foreach를 통해 List길이만큼 update를 5만번 실시함.
for( PrEvntTkpt prEvntTkpt : prEvntTkptList) { 
 
    data = new PrEvntTkpt();
    data.setEvntPtcpNo(prEvntTkpt.getEvntPtcpNo()); // 1 ~ 50000
    data.setModrId(param.getModrId()); // shlee0882
    data.setEvntTkptStatCd("10");    //당첨확정
 
    // 5만건 반복하며 update 실시
    result += commonEventsReadWriteDAO.updateEventWin( data );
}    
cs


1
2
3
4
5
6
7
-- 4. 아래의 같은 update 쿼리를 5만번이나 실행하니 비효율적이고 실행시간이 매우 오래걸리는 단점이 생김.
-- <id= updateEventWin>
    UPDATE pr_evnt_tkpt a
       SET EVNT_TKPT_STAT_CD = #{evntTkptStatCd} -- 10
         , MODR_ID = 'shlee0882'
     WHERE a.CMPN_NO = '2'
       and evnt_ptcp_no = #{evntPtcpNo} -- 1~50000 업데이트문 반복
cs



2.  쿼리에서 select 한 값(5만건)을 한번에 바로 update하기


1. 같은 행사번호에 10만원~20만원 사이 구매한 고객이 5만명이고 이 5만명이 각각 다른 응모자참여번호가 들어갈때

2. 응모자 5만명을 모두 당첨처리를 하기 위해선

3. 5만명에 대한 각각의 응모자참여번호를 서브쿼리로 구해와 

4. 응모자참여테이블의 응모자참여번호에 해당하는 당첨상태 코드를 update 시킨다.

5. select한 값을 한번의 쿼리 수행을 통해 5만건 모두 update 시키고 있다.

6. select한 값을 update치면서 DB Lock이 걸릴수 있다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- 1. 같은 행사번호에 10만원~20만원 사이 구매한 고객이 5만명이고 이 5만명이 각각 다른 응모자참여번호가 들어갈때
-- 2. 응모자 5만명을 모두 당첨처리를 하기 위해선
-- 3. 5만명에 대한 각각의 응모자참여번호를 서브쿼리로 구해와 
-- 4. 응모자참여테이블의 응모자참여번호에 해당하는 당첨상태 코드를 update 시킨다.    
-- 5. select한 값을 한번의 쿼리를 수행을 통해 5만건 모두 update 시키고 있다.
UPDATE  pr_evnt_tkpt a -- 응모참여 테이블
         INNER JOIN (SELECT b.EVNT_PTCP_NO
                          , SUM(b.PUR_RCGN_AMT) as PUR_RCGN_AMT
                       FROM pr_evnt_ptcp_ord b -- 응모참여 주문테이블
                      WHERE b.CMPN_NO = '1'
                      GROUP BY b.EVNT_PTCP_NO, b.CMPN_NO
                     HAVING SUM(b.PUR_RCGN_AMT) >= 100000
                        AND SUM(b.PUR_RCGN_AMT) < 200000 
         ) b
            ON a.EVNT_PTCP_NO = b.EVNT_PTCP_NO
           SET a.EVNT_TKPT_STAT_CD = '10'        -- 당첨확정
             , a.MODR_ID = 'shlee0882'
         WHERE a.CMPN_NO = '2'
cs




1. String to LocalDateTime, String to LocalDate




1
2
3
4
5
6
7
8
9
10
11
12
13
14
// String to LocalDateTime
String issueDate = "20180604"
String tempDate = issueDate.substring(04)+"-"+issueDate.substring(46)+"-"+issueDate.substring(68)+" 00:00";
 
//  tempDate = "2018-06-04 00:00"
LocalDate tempDate2 = LocalDate.parse( issueDate , DateTimeFormatter.BASIC_ISO_DATE); // 2018-10-04
 
//  tempDate2 = "2018-06-04"
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime localDateIssueDate = LocalDateTime.parse(tempDate, formatter); // localDateIssueDate "2018-06-04T00:00"
 
// String to LocalDate
DateTimeFormatter dateformatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate a = LocalDate.parse("2018-06-04",dateformatter); // LocalDate 2018-06-04
cs



2. LocalDateTime to LocalDate, LocalDate to LocalDateTime



1
2
3
4
5
6
7
8
9
10
11
12
// LocalDateTime to LocalDate 
LocalDateTime localDateTime = LocalDateTime.parse("2018-06-04T00:00");
 
LocalDate localDate = localDateTime.toLocalDate(); // localDate : 2018-06-04     
 
// LocalDate to LocalDateTime
 
LocalDate date = LocalDate.parse("2018-06-04");        // 2018-06-04
 
LocalDateTime localDateTime1 = date.atStartOfDay();     // 2018-06-04T00:00
LocalDateTime localDateTime2 = date.atTime(13,15);      // 2018-06-04T13:15
LocalDateTime localDateTime3 = date.atTime(16,0540);    // 2018-06-04T16:05:40
cs



3. LocalDate, LocalDateTime Compare 비교하기



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
// 1. LocalDate compareTo
LocalDate startDt = LocalDate.of(201864);
LocalDate endDt = LocalDate.of(201866);
LocalDate issueDt = LocalDate.of(201865);
 
System.out.println(startDt.compareTo(endDt));  // startDt(2018, 6, 4) > endDt(2018, 6, 6) -> return -1
System.out.println(startDt.compareTo(startDt));    // startDt(2018, 6, 4) = startDt(2018, 6, 4) -> return 0
System.out.println(endDt.compareTo(startDt));  // endDt(2018, 6, 6) > startDt(2018, 6, 4) -> return 1
 
// startDt(시작일자)와 endDt(종료일자) 사이에 issueDt(발행일자)가 들어가는지 비교하기 위해 조건문을 작성하면
 
if(issueDt.compareTo(cmpnStrtDttm) == -1 // 발행일이 시작일보다 작거나
        || issueDt.compareTo(cmpnEndDttm) == 1 ) { // 발행일이 종료일보다 크면
    throw new exception("발행일자가 시작일자와 종료일자 기간사이에 속해있지 않습니다.");
}
 
// 2. LocalDateTime isBefore, isAfter
 
// LocalDateTime형식의 strtDt : 2018-06-04T00:00 , endDt: 2018-06-05T00:00, isuueDt: 2018-06-04T00:00
LocalDateTime strtDt = LocalDateTime.parse("2018-06-04T00:00");
LocalDateTime endDt = LocalDateTime.parse("2018-06-05T00:00");
LocalDateTime isuueDt = LocalDateTime.parse("2018-06-04T00:00");
 
if( (isuueDt.isAfter(strtDt) // 발행일이 시작일보다 커야(이후여야)하고
    && isuueDt.isBefore(endDt) ) // 발행일이 종료일보다 작아야(이전이어야)하고
        || (isuueDt.isEqual(strtDt) // 발행일이 시작일과 같을경우
        || isuueDt.isEqual(endDt) )){ // 발행일이 종료일과 같을경우
        System.out.println("발행일이 시작일과 종료일 사이에 속해있음."); 
}else{
    throw new exception("발행일이 시작일과 종료일 사이에 속해있지 않습니다.");
}
 
if( (!isuueDt.isAfter(strtDt) // 발행일(06-04)이 시작일(06-05)보다 크지(이후이지) 않고
    && !isuueDt.isBefore(endDt) )) // 발행일(06-04)이 종료일(06-05)보다 작지(이전이지)않고
{
    throw new exception("발행일이 시작일과 종료일 사이에 속해있지 않습니다.");
}else{
        System.out.println("발행일이 시작일과 종료일 사이에 속해있음."); 
}
cs


LocalDate, LocalDateTime의 형식과 Compare 방법에 대해 알 수 있었다.



자바 동적변수 생성 테스트, 해결방법은?


1. 첫번째 시도



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 엄청 긴 숫자와 문자가 섞인 문자열이 있는데 
// 5자리씩 잘라서 이 자릿수가 맞는지 검증해야 했었다.
// 어떻게하면 효율적으로 문자열을 잘라내 저장하여 활용할수 있는지 테스트 해보았다.
 
String myString = "ABCDEFGHIJKLMNOPQRSTUVWXY";
 
// 1번째 방법 시도 : 필요한 변수를 모두 선언한 뒤 값 넣기
String firstNo ="";
String secondNo ="";
String thirdNo ="";
String fourthNo ="";
 
firstNo      = myString.substring(05);       // ABCDE
secondNo     = myString.substring(510);       // FGHIJ
thirdNo      = myString.substring(1015);    // KLMNO
fourthNo      = myString.substring(1520);    // PQRST
 
// 각각의 값을 다르게 관리하기 위해 매번 필요한 변수명을 만들어줘야하나 라는 생각이 들어.
cs


결과


firstNo  : ABCDE

secondNo : FGHIJ

thirdNo  : KLMNO

fourthNo : PQRST



2. 두번째 시도



1
2
3
4
5
6
7
8
9
10
// 2번째 방법 시도 : 자바로 동적변수를 만들수 있나?
for(int i=0,  j=0; i<=3; i++, j=j+5) {
    // ABCDE , FGHIJ, KLMNO, PQRST, UVWXY
    // String a0 = "ABCDE", String a1 = "FGHIJ", a2, a3 ... 
    // 동적변수 선언 및 5자리씩 값을 초기화 해보려고 시도
    
    String k = String.valueOf(i); // i를 String으로 치환후 k로 재선언
    String a+= myString.substring(j, j+5);
    // 동적변수 만들기 불가 .. 같은 String이어도 +기호를 사용해 만들순 없었다.
}
cs


결과


FAIL



3. 세번째 시도



1
2
3
4
5
6
7
8
//  3번째 방법 시도 : Map을 이용해봄.
HashMap<Integer, String> myHashMap = new HashMap<Integer, String>();
for(int i=0,  j=0; i<=3; i++, j=j+5) {
    myHashMap.put(i, myString.substring(j, j+5));
}
myHashMap.forEach((k,v)->{
    System.out.println("key: "+k+"value: "+v); // 해결가능
});
cs


결과


key: 0 value: ABCDE

key: 1 value: FGHIJ

key: 2 value: KLMNO

key: 3 value: PQRST

key: 4 value: UVWXY





1. MySQL 만 나이 구하는 쿼리




1
2
3
4
5
6
7
8
9
10
11
12
13
14
 -- 만 나이 구하기
select 2 > 1 as compareNum1 -- true return 1 
     , 2 > 3 as compareNum2 -- false return 0
     , a.birthdt -- 생년 월일은 19900804
     , year(a.birthdt) as birthYY -- 생년 구하기 1990
     , date_format(a.birthdt, '%m%d') as birthMMDD -- 생일 월일 구하기 0804
     , date_format(now(), '%m%d') as nowMMDD -- 현재 월일 구하기 0515
     , year(now()) - year(a.birthdt) as unconfirmedAge -- 생일이 지났는지 확인하지 않는 나이 28 
     , (date_format(a.birthdt, '%m%d'> date_format(now(), '%m%d')) as calPassBirth -- 1
    --  생일월일 > 현재월일 true 1 false 0 true일경우 생일 안지난것. false일 경우 생일 지난것.
     , (year(now()) - year(a.birthdt)) - (date_format(a.birthdt, '%m%d'> date_format(now(), '%m%d')) as confirmedAge -- 만 나이 27       
  from pr_evnt_win a
 where a.cmpn_no = '20335' -- 조건1
   and a.evnt_tkpt_stat_cd IN ('175''180''190''200'-- -- 조건2
cs



결과


 compareNum1

 compareNum2

 birthdt

 birthYY

 birthMMDD

 nowMMDD

 unconfirmedAge

 calPassBirth

 confirmedAge

 1

 0

 19900804

 1990

 0804

 0515

 28

 1

 27






1. MySQL 테이블 컬럼 커멘트 보기



1
 SHOW FULL COLUMNS FROM 테이블명;
cs



1. AnyEdit 플러그인 사용 이유



Model을 만들때 테이블 컬럼명을 기준으로 기본을 잡는경우가 많다.


테이블 컬럼명은 대부분 Underscores(_표시) 예) dc_type_cd 로 되어있는 경우가 많은데


테이블 _(언더바)를 지우고 dcTypeCd인 카멜로 변환시켜주는 에디트 플러그인이 AnyEdit 플러그인이다.



2. AnyEdit 플러그인 기능 설명



2.1 소문자로 바꾸기 :  Ctrl+Alt+L, 


dcTypeCd -> dctypecd



2.2 대문자로 바꾸기 :  Ctrl+Alt+U


dcTypeCd -> DCTYPECD



2.3 Camel(낙타) <-> Underscores(_표시) : Ctrl+Alt+K


private String dc_type_cd -> private String dcTypeCd



3. AnyEdit 설치방법



eclipse Help > Eclipse MarketPlace  > AnyEdit 검색 > install



이 플러그인을 사용함으로써 Model 작성시 시간과 오타 모두를 줄일수 있다고 생각한다.






사용자가 데이터를 입력해서 해당 내용을 저장할때 그 값이 유효한지 안 한지 확인하는 방법은 필수적이다.


저장버튼을 누를때 Validation 로직을 태워 return하는 flag 값이 true이냐 false이냐에 따라 저장로직을 탈지 안탈지 결정할 수 있다.


그 중 이메일 유효성 체크 로직을 보려고 한다.



1. 정규표현식 이용한 Email Validation 만들기


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
scwin.validate = function() {
    var list = dlt_testerList.getAllJSON();
    console.log(list);
    for(var i=0; i<list.length; i++){ 
        if(checkEmail(list[i].emailAddr) != true){ // 이메일형식이 맞는지  확인한다.
            return false;
        }    
    }        
    return true;
};
 
// 이메일 정규표현식 체크
function checkEmail(myValue) {        
    var email = myValue;
    var exptext = /^[A-Za-z0-9_\.\-]+@[A-Za-z0-9\-]+\.[A-Za-z0-9\-]+/;
        if(exptext.test(email)==false){
            //이메일 형식이 알파벳+숫자@알파벳+숫자.알파벳+숫자 형식이 아닐경우            
            alert("이메일형식이 올바르지 않습니다.");
            return false;
        };
        return true;
};
 
scwin.btn_save_onclick = function(e) { // 저장할 때 이메일형식 validation 체크함.
    if!scwin.validate() ){ // scwin.validate()에서 false가 나오면 안으로 진입 
        return;
    }
    
    if(confirm("저장 하시겠습니까?") ){
        $w.executeSubmission("sbm_insertTester");
    }
};
cs



return 되는 값이 true 일때만 confirm 창이 뜨게 되고 false 일 경우 저장로직을 타지 않게 되는것을 확인할수 있었다.






1. 문자열의 마지막 문자를 자르는 방법



1
2
3
4
5
var myDcVal = "100000원"
 
myDcVal = myDcVal.slice(0,-1);
 
console.log(myDcVal);
cs


출력결과

100000



2. 문자열의 3자리마다 콤마 찍어주기



1
2
3
4
5
6
7
8
9
10
11
var myData = "1000000";
 
myData = AddComma(myData);
 
function AddComma(data_value) {
 
 return Number(data_value).toLocaleString('en');
 
}
 
console.log(myData);
cs


출력결과

1,000,000



3. 문자열의 특정문자(콤마) 없애기



1
2
3
4
5
6
7
var myData = "1,000,000";
 
if(myData.indexOf(","!= -1){ // 콤마가 있다면
  myData = myData.replace(/(,)/g, ""); // 콤마를 ""로 replace함                
}
 
console.log(myData);
cs


출력결과

1000000



4. 문자열의 특정 위치 찾기


var myString1 = "Hello,World"


다음은 문자열의 특정위치를 찾기위한 Hello,World의 위치값을 표기한 것이다.

0H1e2l3l4o5,6W7o8r9l10d11



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
// 1. substring([시작위치], [종료위치]);
 
var myString1 = "Hello,World"
 
myString1 = myString1.substring(0,5);
console.log(myString1);
 
// 출력결과 Hello
 
/*****************************************/
 
// 2. substr([시작위치], [길이]);
 
var myString1 = "Hello,World"
 
myString1 = myString1.substr(6,5)
console.log(myString1);
 
// 출력결과 World
 
/*****************************************/
 
// 3. indexOf([검색 문자열]);
 
var myString1 = "Hello,World"
 
console.log(myString1.indexOf(","));
 
// 출력결과 5
 
/*****************************************/
 
// 4. lastIndexOf([검색 문자열]);
 
var myString1 = "Hello,World"
 
console.log(myString1.lastIndexOf("o"));
 
// 출력결과 7
 
/*****************************************/
cs


다음과 같은 방법을 통해 문자열의 필요한 값을 추출할 수 있었다.



+ Recent posts