'전체 글'에 해당되는 글 384건

  1. 2020.03.31 전자정부 프레임워크에 트랜잭션 적용하기 2
  2. 2020.03.30 UML - 관련 정리
  3. 2020.03.27 클래스 기반 언어 vs 자바스크립트
  4. 2020.03.25 Function, Method, Property 의 차이 및 정의
  5. 2020.03.23 데이터베이스에서 null 과 빈 문자열(empty string)의 차이점
  6. 2020.03.23 Maria DB 1
  7. 2020.03.19 Tomcat 프로세스 강제종료
  8. 2020.03.18 객체 얕은 복사(shallow copy)와 깊은 복사(deep copy)
  9. 2020.03.03 이력 테이블에서 최종 데이터만 조회하기
  10. 2020.02.23 CSS기본문법, 속성, 선택자

전자정부 프레임워크에 트랜잭션 적용하기

|

하루의 삽질을 거쳐서...

 

간신히 찾은 나의 방법

1. dispatcher-servlet.xml

상단 beans 에 
xmlns:tx="http://www.springframework.org/schema/tx"
추가

하단 xsi:schemaLocation 에
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
추가

<!-- 트랜잭션 처리를 위한 추가 -->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

<!-- 트랜잭션 처리를 위한 추가 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>

2. context-transaction.xml

	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>

	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="*" rollback-for="Exception"/>
		</tx:attributes>
	</tx:advice>

	<aop:config proxy-target-class="true">
		<aop:pointcut id="requiredTx" expression="execution(* nepp.att.service.*.*(..))"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="requiredTx" />
	</aop:config>
    
3. serviceImpl
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})

4. service가 implements 하는  인터페이스 에도
@Transactional 선언해야.

5. 그 외
DB의 오토커밋 설정여부 확인?

-- Maria DB
show variables like 'autocommit%'; // autocommit 설정값 확인

SET AUTOCOMMIT = TRUE;  --> 설정 // autocommit 설정 또는 해제
SET AUTOCOMMIT = FALSE; --> 해제

COMMIT; // 트랜잭션 commit, rollback
ROLLBACK;

위는 선언적 처리방법

 

아래는 명시적 처리방법..

주의할 점은 정상일 경우 커밋을 명시안하면 이도저도 아니게 처리가 안된상태로 남는다는것

@Resource(name = "txManager")
protected DataSourceTransactionManager txManager;

~~~

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus txStatus = txManager.getTransaction(def);

~~~~

try { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      ~~~ 각종 INSERT UPDATE 등 DB 문 ~~~
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      txManager.commit(txStatus); //정상일경우 COMMIT;
	  model.put("result", 0);
    } catch (Exception e) {
      e.printStackTrace();
      txManager.rollback(txStatus); //에러날경우 CATCH로 빠져서 ROLLBACK;
      model.put("result", -1);
    }
}

출처: https://dydals5678.tistory.com/121 [아빠개발자의 노트]
And

UML - 관련 정리

|

CHAP.3 Class Diagram

* Property
    - class의 구조적인 특성을 나타 낸다.
    - 두 가지의 표기법으로 구성된다.
        1) 속성 (Attributes)
        2) 연관 (Associations)

* Attributes (속성)
    - Class box에 한줄로 표시된다.
    - 표현 방법
        # visibility name : type multiplicity = default {property-string}
        # Ex) - name : String [1] = "Untitled" {readOnly}
        # Class Diagram 그림
            



* Associations (연관)
    - Property를 표시 하는 또 다른 방법
    - 저자는 보통 Type이나 Boolean 같은 일반적인 것은 Attributes 방법으로 표시 하고, 중요한 class 는  Association 방법으로 표시 한다.
    - Association 그림
        

* Multiplicity (다중성)
    - Property내에 들어 갈 수 있는 객체의 수
    - 속성 부분의 예제중  String[1] 부분 이다. - name : String [1] = "Untitled" {readOnly} 
    - Mulitplicity 항목
        1) Optional - 하한이 0
        2) Mandatory - 하한이 1
        3) Single-valued - 상한이 1
        4) MultiValued - 상한이 1 이상(흔히 '*'로 표현)
    - 속성에 순서가 의미가 있는 경우 {ordered}를 붙인다.
    - 속성에 중복을 허용 한다면 {nonunique}를 붙인다.
    - 기본값을 명확하게 표현하려면 {unordered}, {unique} 사용
    - 중복을 허용하는 경우 {bag}

* Bidirectional Associations
    - class간에 서로 연관된 property
    - 예제 diagram (일반적으로 Propertye Type이 복수인 경우 cars 라고 namming한다.)
        

    - 속성을 명확하게 표현하기 위해 방향성 화살표를 추가 한다 (일반적으로 화살표 연관 표시는 동사형으로 표시).
        

    - 양방형 association의 경우 association의 한쪽이 둘간의 관계를 통제 해야 한다.

* Operation
   
- Class가 수행 하는 action
    - Operation의 표기
        # visibility name (parameter-list) : return-type {property-string}
        # Parameter 표기
            + direction name : type = default value
        # Ex) + balance0n (date : Date) : Money
    - Visibility
        # '-': Private, '#': Protected, '+': Public
    - Operation의 Type
        1) 시스템의 상태를 변경하는 Operation - {query} 로 표시
        2) 시스템의 상태를 변경하지 않는 Operation - {modifier} 또는 {command}
        # {query} 와 {command} 판별 기준은 시스템 변경 여부를 외부에서 관찰 가능 여부에 따른다.
        # Cache 내용이 변경 되었어도 외부에서 변경 여부를 확인 할 수 없으므로 {query}에 해당한다.
        # 일반적로 modifier 또는 command는  void 형을 리턴 하는 것으로 정의 한다.
    
- Operation과 Method의 차이
        # Operation - 객체에서 호출되는 Procedure
        # Method - Procedure 자체
        # If you have a supertype with three subtypes, each of which overrides the supertype's getPrice operation, ou have one operation and four methods that implement it

* Generalization
    - Ex) 기업 고객와 일반 고객
        # 기업고객와 일반 고객 class가 customer class로 부터 상속을 받은 경우 기업 고객은 일반고객의 인스턴스가 가능하다.
    - 소프트 웨어 관점에서 일반화는 상속과 연관이 있다.
    - 상속의 효과적인 사용은 substitutability 이다.
    - 위의 예제에서 기업 고객은 고객으로 대치가 가능하며, 이상없이 동작해야 한다.
    - inheritance는 강력한 방법이지만 substitutability를 만족시키는데 overhead가 존재 한다.
    - 디자인 패턴에는 subtyping without subclassing 방법들이 많이 존재 한다.

* Note & Comment
    - 단독으로 사용하거나 설명하고자 하는 요소에 점선으로 연결하여 사용한다.


* Dependency
    - Dependency가 존재 하는 것은 한부분의 변화가 다른 한부분에 영향을 미치는 것이다.
    - 그림으로 표현된 아래 예제는 multilayered app.에서 발생할 수 있는 dedpedency를 보여준다.
        


    - Dependency는 방향성을 가진다.
    - 위의 예제에서 Benefits Window 는 Employee Data Gateway, Benefits Data Gateway와는 간접적인 dependency를 가진다.
    - 프로젝트 수행시 가능하면 dependency를 줄이는 것을 base rule로 삼아야 한다.
    - Class Diagram에서 모든 dependency를 표현하는 것은 쓸모 없는 일이다.
    - 전달하고자 하는 특별한 부분과 밀접한 연관이 있을 경우에만 선택적으로 dependency를 표현 하는 것을 추천한다.
    - 저자가 dependency를 사용하는 경우
        # 어떤 객체가 다른 객체에 parameter로 전달 되는 경우에 사용한다.
        # 이경우 <<parameter>>, <<local>>, <<global>> 과 함께 사용하게 된다.
    - Dependency 분석은 툴을 이용하는 것이 이상적이다.
    - Dependency에서 사용하는 Keyword 일부
        


* Constraint Rules
    - Association, Property, Generalization 은 제약을 명시 하는데 중요한 역할을 한다.
    - Class Diagram은 제약을 표현 하는데 중요한 수단이다.
    - Constraint 을 사용하는 규칙은 '{}' 안에 constraint를 명시 한다.

* When to Use Class Diagrams
    - Class Diagram은 UML의 중요한 요소(backbone) 이다.
    - Class Diagram은 단순한 것부터 시작해라
    - 모든 것에 모델을 그리지 말고, 중요한 부분에 집중해라
    - 다수의 diagram 보다 적은 수의 diagram을 사용 하면서 갱신하는것을 추천한다.
    - Class diagram을 사용할때는 구조에 너무 신경을 써서 action을 무시 해서는 안된다.

* Reference
    UML Distilled A Brief Guide To The Standard Object Modeling Language Chapter 3. Class Diagram

 

CHAP.4 Sequence Diagram

 

* Interaction Diagram
    - 객체들간의 cowork를 설명한다.

* UML에서는 몇가지 interaction diagram이 있다.
    - 그중 Sequence Diagram이 가장 많이 사용된다.

* Sequence Diagram의 장점
    - Diagram 에서 객체간의 동작을 설명할 필요 없이 잘 표시 되어 있다.

* 중앙 집중형 Seq. Diagram 과 분상형 Seq. Diagram
    - 분산형이 객체 지향 설계에 적합하다.
    - 중앙 집중형(Centralized Control)은 모든 로직을 한곳에서 관리 하기 때문에 코드가 복잡해 진다.
    - 분산형(Distributed Control)은 각 객체가 행동에 책임을 가지고 있기 때문에 코드 단순하다.
    - 중앙 집중형에서는 an Order 객체가 aProduct 객체를 리턴 받는다. 모든 부분에서 리턴을 명시하면 diagram이복잡해 진다.
   중요한 부분만 리턴을 명시 하였다.
    - aProduct 객체는 'an order Line'에서 객체를 생성하여 리턴 받으며 getPricingDetails를 호출당하고 소멸된다.

           



    - 첫 번째 메시지는 확인되지 않은 source로부터 발생되기 때문에 메시지를 생성한 참가자가 없다. 이런 메시지를 found message라고 한다.
    - Parcipants의 Seq. Diagram 표현 Syntax
        # name : Class
        # Class는 option 이지만, class를 명시할 경우 ':'를 붙인다.
 
* Creating and Deleting Participants (참가자 생성 & 삭제)
    - Sequence Diagram 참가자 생성 삭제 표시 방법
        # participants 삭제는 'X' 표로 한다.
        # 'X' 표를 향하는 메시지 화살표는 한 참가자가 다른 participants 를 삭제 하는 것을 표시
        # Life line 끝에 'X'표는 participants 가 자기 자신을 삭제 하는 것을 표시
    - Participants Create & Delete 그림
        

* Loops, Conditionals, and the Like (루프 조건문 등등)
    - Seq. Diagram에서의 loop, conditional statement 표현
        # Seq. Diagram에서는 loop, conditional 을 표현 하기에 적합하지 않다.
        # Control structures를 표시 하기에는 activity diagram을 사용하거나 코드 자체를 이용하는 것을 추천한다.
    - Seq. Diagram에서의 loop, conditional statement 표현 예제
        

    - 'loop' operator
        # 반복 조건을 가드에 표시 한다.
    - 'alt' operator
        # 각 조각에 조건을 표시 한다.
    - 'opt' operator
        # 하나의 영역만 조건에 존재 하는 경우에 사용한다.
    - Interaction Frame의 Operator Table
        

    - UML 1 에서의 control logic 표기
        # UML 1에서는 mutual exclusive를 표시 할 수 없다
        # UML 1에서는 반복 표시자는 '*' 를 사용한다.
        # 하나의 loop에서 여러개의 메시지가 나오는 경우 표현에 적합하지 않다.
        # 그림 예제
            

    - UML 표준 에는 데이터를 전달하는 표기 법이 없다.
    - 대부분의 사람들이 이것을 표시 하기 위해 Data Tadpole를 사용한다. (비공식적)

* Seq. Diagram에서 존건문 표기에는 다양한 도식 사용이 가능 하지만, 저자는 이를 표현 하는 것을 코드가 가장 적합하다고 생각한다. 특히 interaction frame이 매우 복잡해지면 diagram의 주제를 흐리기 때문에 저자는 이런 경우 pseudomessages를 선호한다.

* Synchronous and Asynchronous Calls (동기, 비동기 호출)
    - Synchronous & Asynchronous call은 화살표 머리 모양으로 표시한다.
    - Synchronous message
        # filled arrowheads (머리가 채워진 화살표)
        # 호출하는 객체가 return을 대기해야 하는 경우
    - Asynchronous message
        # stick arrowheads
        # 호출하는 객체가 return을 대기할 필요가 없는 경우

* When to Use Sequence Diagrams
    - 하나의 Use case에서 객체간의 interaction을 확인 해야 하는 경우에 사용한다.
    - Action의 정의를 표현하는 데는 적합하지 않다.
    - 만약, 여러 use case에 걸친 하나의 객체의 behavior 을 확인 하고 싶으면 state diagram을 사용해야 한다.
    - 만은 user case 또는 thread에서 동작하는 객체의 behavior 을 보고 싶으면  activity diagram을 사용해야 한다.
    
* Reference
    UML Distilled A Brief Guide To The Standard Object Modeling Language Chapter 4. Sequence Diagram

 

출처 : http://gggura.egloos.com/3452986

'DevTools' 카테고리의 다른 글

이클립스 톰캣 연동  (0) 2020.04.20
Tomcat context 설정  (0) 2020.04.02
Tomcat 프로세스 강제종료  (0) 2020.03.19
전자정부프레임워크  (0) 2020.02.06
Server에서 Tomcat 클린하기  (0) 2020.01.08
And

클래스 기반 언어 vs 자바스크립트

|
  1. 자바스크립트에는 클래스가 없다.
  2. 함수 내부에서 this의 의미는 클래스 언어에서 말하는 인스턴스 자신이 아니라 함수에게 전달된 컨텍스트다.
  3. 클래스 언어는 인스턴스를 기준으로 메서드를 호출하는 문법만 존재하나, 자바스크립트는 함수에게 인스턴스를 전달하는 방법도 존재한다.
  4. new는 근본적으로 오브젝트를 만들어낸다.
  5. new 뒤에 오는 것은 클래스가 아니라 그저 함수다.
  6. new로 생성한 오브젝트는 new에 전달된 함수의 prototype이라는 속성을 자신의 __proto__에 참조로 잡게 된다.
  7. new가 실행되면 3단계(오브젝트생성, prototype할당, 함수호출)의 순차적인 작업이 일어난다.

출처 : https://www.bsidesoft.com/?p=318&

And

Function, Method, Property 의 차이 및 정의

|

함수(function)

object type중의 하나로서 반복하여 사용되는 독립된 명령(subroutine)

반복하여 사용되는 독립된 명령이라는 점에서는 다른 언어와 유사하지만, Javascript에서 함수(function)는  독립된 정의가 아닌 객체(object)의 일종으로 여겨진다는 점에서 다르다.

즉,  함수(function)도 객체(object)로 취급된다.

 

 

프로퍼티(property)

클래스 내부에 만드는 변수를 프로퍼티 라고 부름. (멤버변수 라고도 함)

프로퍼티에는 주로 객체 내부에서 사용하는 일반적인 정보와 객체 내부 함수(메서드) 에서 처리한 결과값이 저장.

-> OOP(객체 지향 프로그래밍)에서 흔히 말하는 getter/setter 'method'의 역할을 수행하면서 마치 데이터 멤버(필드)에 접근하듯이 사용할 수 있는 class member

 

‘키(key)와 값(value)이 연관된 객체(object)의 부분’
이를 풀어보면, 객체 내에서 선언된 변수()를 의미한다고 볼 수 있다.
다른 언어와의 차이점은, 다른 언어에서는 배열 내부에 있는 값들을 요소()라고 부르지만 Javascript에서는 배열 또한 객체로 표현되기 때문에 요소와 Property는  Javascript에서 사실상 동일하다.

자바스크립트를 공부하다보면, 변수, 함수, 객체, 프로퍼티 와 같은 단어를 많이 사용하고 접하게 된다.
처음 접할때는 변수 == 프로퍼티 라고 이해를 하게 되지만,
시간이 지나고 조금더 고민하다보면 뭔가 미묘한 차이들이 있다.
그래서 누군가 이 함수에서 변수는 무엇이고 프로퍼티는 무엇이냐 ?
라고 물어보게 된다면 더욱 더 헷갈리게 된다. 그래서 이번기회를 통해 조금 정리해보았다.
예를들어 아래와 같은 코드가 있다고 하자.

var a = "test";
일반적으로 변수는 var 로 선언을 하게 된다.
여기서 a 는 해당 스코프 안의 변수 이다.
절대 해당 스코프에서 프로퍼티라고는 하지 않는다.
하지만 만약에 다음과 같이 작성한다고 하자.

this.b = "test";
this를 통해서 b를 선언하게 되면, b 는 해당 객체의 프로퍼티가 되게 된다.
단순하게 var로 선언하면 변수, this 로 선언하면 프로퍼티 라고한다.

설명을 좀더 자세히 하기 위해 전체 코드를 작성해보겠다.
-------------------------------------------------
var setMyName = function( value ){
  var name = value;
  this.name = value;
};
var setName = new setMyName( "kazikai" );
console.log( setName.name ); //kazikai

위 코드에서 발생하는 name 은 var name 으로 저장된 값일까? this.name 으로 저장된 값일까?

-> 정답은 this.name 으로 저장된 값이다.
이유는 setName 이란 변수는 setMyName의 인스턴스를 통해 만들어진 객체이며,
해당 객체에서 this.name 이라고 선언된 name은 인스턴스로 만들어진 객체의 프로퍼티가 된다.

조금 더 추가 설명을 하자면,
JavaScript에서는 private public 의 개념이 따로 존재하지 않는다.
Public이 외부에서 접근 가능하고 private이 내부에서만 접근가능한 변수라고 한다면,
this 는 public 이고, var는 private 한 변수라고 할 수 있다.

아래는 더글라스 크락포트가 작성한 private 에 관한 개념. 이 개념을 이해하면, 변수와 프로퍼티의 차이점을 더욱 더 자세히 이해할 수 있다.

http://javascript.crockford.com/private.html

 

메서드(method)

클래스에 만드는 함수를 메서드 라고 부르며 멤버함수 라고도 부름.

메서드는 주로 객체의 프로퍼티 값을 변경하거나 알아내는 기능과 클래스를 대표하는 기능이 담기게 됨.

 

‘property의 값인 함수(function)’
즉, 객체 내에서 정의된 함수를 의미하는 단어이다.
특히 Javascript의 method에서 this는 method가 속한 객체를 의미한다.

var person = {
		name: '홍길동',
		friend: '임꺽정',
		eat: function(food){
			alert(this.name + '이 ' + this.friend + '과 ' + food + '을 먹습니다.');
		}
};
person.eat('밥'); // 메소드 호출 : '홍길동이 임꺽정과 밥을 먹습니다.'

 

클래스

함수는 기능을 포장하는 기술 이라면 클래스는 그렇게 만들어진 변수와 함수 중 연관있는 변수와 함수를 선별해 포장하는 기술.

포장하는 이유는 객체 단위로 코드를 그룹화하고 재사용하기 위함.

 

 

인스턴스

클래스를 사용하려면 일반적으로 인스턴스를 생성해서 사용.

한 페이지 내에 두개 이상의 같은 동작을 하는 UI를 만들경우 두개의 클래스를 만드는 것이 아니라 하나의 클래스를 만든 후 두개의 인스턴스를 만들어 사용.

 

 

객체

객체라는 용어는 인스턴스의 다른 말 (두 용어 모두 클래스의 실체를 나타냄.)

명확히 구분해서 설명하면 인스턴스 라는 용어는 new 키워드를 이용해 클래스의 실체를 생성할 때 주로 사용하며 객체라는 용어는 인스턴스 생성 후 클래스 에서 제공하는 프로퍼티와 메서드를 사용할 때 주로 사용.

 

 

 


출처:
https://recoveryman.tistory.com/387 [회복맨 블로그]

https://github.com/kyukyukyu/oop-mentoring/issues/2

And

데이터베이스에서 null 과 빈 문자열(empty string)의 차이점

|

테이블의 NULL 허용 필드에 데이터를 넣을 때 빈 문자열(empty string)을 넣으면 어떻게 될까요? 아래의 두가지 쿼리가 어떻게 동작할지를 말하는 것입니다.

 

INSERT INTO tb_test (id, name) VALUES (1, NULL); INERRT INTO tb_test (id, name) VALUES (2, '');

 

1. Oracle

 

오라클에서는 NULL과 빈문자열 '' 이 모두 NULL 로 처리 됩니다. 위에서 id 가 1, 2 인 행의 name은 모두 NULL 이 들어갑니다.

 

SELECT * FROM tb_test WHERE name IS NULL;

 

위와 같이 쿼리하면 id가 1, 2인 행이 모두 조회됩니다. 데이터베이스에서 NULL은 등호(=)로 비교할 수 없습니다. 반드시 IS NULL 또는 IS NOT NULL 을 사용해서 판별하여야 합니다.

 

값이 NULL인 문자열의 길이는 얼마가 나올까요?

 

SELECT LENGTH(name) FROM tb_test WHERE name IS NULL;

 

답은 NULL 입니다. 데이터베이스에서 NULL을 다룰 때는 항상 주의해야 합니다. 계산에 NULL 이 사용 되면 0처럼 동작하는것이 아니라 결과가 NULL이 되어 버립니다.

 

 

2. MySQL(MariaDB)와 SQLServer

 

MySQL(MariaDB)와 마이크로소프트의 SQLServer에서는 빈 문자열이 입력됩니다.

 

SELECT * FROM tb_test WHERE name = '';

 

위와 같이 조회 하면 id가 2인 행이 나옵니다.

 

SELECT * FROM tb_test WHERE name IS NULL;

 

이렇게 조회 하면 id가 1인 행이 나옵니다.

 

 

각각에서 빈 문자열 필드의 길이를 구해보면 0이 나오게 됩니다.

 

-- MySQL SELECT LEN(name) FROM tb_test WHERE name = ''; -- SQLServer SELECT LENGTH(name) FROM tb_test WHERE name = '';

 

데이터베이스 NULL 을 잘 다루는 것은 매우 중요합니다. 데이터베이스에서 값을 조회한 프로그램에서 오류를 낼 수 도 있고, 계산등에서 값이 맞지 않을 수도 있기 때문입니다.



출처: https://offbyone.tistory.com/226 [쉬고 싶은 개발자]

 

mysql에서 공백과 null 동시 체크
여러가지 방법이 있겠으나 제가 선호 하는 방식에 대한 설명입니다.

NULLIF(컬럼명,'') IS NULL
NULLIF를 이용하여 해당 컬럼명이 '' 공백과 같다면 null 치환하여 해당 컬럼이 null인지 여부를 체크하는 방식입니다.

관련 참고 함수

1. CASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN result  ...] [ELSE result] END
switch 문과 유사항 방식

    CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
switch 문 - IF문 의 조합형

2. IF(expr1, expr2, expr3)
  : expr1이 TRUE 이면 expr2를 리턴하고, 그렇지 않은 경우 expr3를 리턴한다.

3. IFNULL(expr1, expr2)
  : expr1이 NULL이면 expr2를 리턴하고, NULL이 아니면 expr1을 리턴한다.

4. NULLIF(expr1, expr2)
  : expr1 = expr2가 TRUE이면 NULL을 리턴하고, 그렇지 않으면 expr1을 리턴한다.
    이것은 CASE WHEN expr1=expr2 THEN NULL ELSE expr1 END 와 같다.
And

Maria DB

|

-- root 비번 잊었을 경우(2020.05.01 추가)

 

-- pom.xml 설정
<!-- MariaDB 연동을 위해 아래 dependency 추가 --> 
		<dependency>
			<groupId>org.mariadb.jdbc</groupId>
		    	<artifactId>mariadb-java-client</artifactId>
		    	<version>2.4.1</version>
		</dependency>
        
<!--
for MariaDB : 사진에서 주석으로 막혀있던 dependency중 아래는 삭제

        <dependency>
            <groupId>ojdbc</groupId>
            <artifactId>ojdbc</artifactId>
            <version>14</version>
            <scope>system</scope>
            <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/ojdbc-14.jar</systemPath>
        </dependency>
       -->
       
<!--
		for MariaDB : 아래의 메모리DB dependency는 삭제
		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<version>2.3.2</version>
		</dependency>
		 -->
       
-- context-datasource.xml 설정
<!-- for MariaDB  -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.mariadb.jdbc.Driver"/>
        <property name="url" value="jdbc:mariadb://127.0.0.1:3306/NEPP" />
        <property name="username" value="scott"/>
        <property name="password" value="tiger"/>
    </bean> 
        
-- 오류 해결 java.sql.SQLException: No database selected

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  <property name="url" value="jdbc:mysql://localhost:3306/이부분에 스키마 이름"></property>
  <property name="username" value="유저명"></property>
  <property name="password" value="비번"></property>
</bean>
    
-- 권한 관련 오류
사용자 계정에 대한 관리는 mysql database 에서 합니다.
mysql>use mysql;
-- 사용자 계정 생성
mysql> create database database명;
mysql> grant all privileges on database명.* to 아이디@localhost
identified by '비밀번호' with grant option;
mysql> FLUSH PRIVILEGES;

-- Incorrect integer value: '' for column ★★★★★★★★★★
my.ini 파일에서...
[mysqld]
sql-mode="EMPTY_STRING_IS_NULL"

입력 후 저장 재시작 해결...
-> 이렇게 하면 빈값 조회시 null로 되므로 조회가 안됨!!!!!!!!!!!!!!
 
 -> NULLIF(#{DEPT_ISSUPPORTER}, ''), 
 로 ''빈값을 NULLIF로 해서 ''일경우 NULL, 아닐경우 해당값을 리턴하는 것으로 해결!!!

 

마리아 DB vs. Oracle 문법 비교

기능  MySQL(MariaDB) Oracle 
 Null일 경우 값 처리  IFNULL('컬럼 값', '대체 값')  NVL('컬럼 값', '대체 값')
 문자열 합치기  CONCAT('합칠 값1', '합칠 값2', '합칠 값3' )  CONCAT('합칠 값1', '합칠 값2')
- 오라클의 경우 값 2개까지만 병합가능

 또는
 '합칠 값1'||'합칠 값2'||'합칠 값3'
 데이터 1개만 보기  LIMIT 1  WHERE ROWNUM = 1
 (where 조건 절 안에서)
 시스템 현재 시간  NOW()   SYSDATE 
 alias 사용법  as 'alias 명' 또는 alias 명 또는 as alias 명  as alias명 또는 alias 명(자동 대문자 전환)
 대소문자 구분한 값을 보고 싶을 경우,
 as "alias 명" 또는 "alias 명"
 날짜형식 변환  DATE_FORMAT(NOW(), '%Y%m%d')  TO_DATE(SYSDATE, 'YYYYMMDD')
 날짜 표기  '%Y-%m-%d %H:%s'(년도-월-날 시간:분)  'YYYY-MM-DD HH24:MI'
 IF문 활용  IF(조건식 demoTable.empSeq >= 1234,
 참이면 반환할 값, 거짓이면 반환할 값)
 DECODE(조건식, 일치해야하는 조건값,
 참이면 반환할 값, 거짓이면 반환할 값)

 DECODE는 equal(즉, 등호)만 지원할 수 있   다.
 다중 조건  CASE 
        WHEN '비교할 조건1' THEN '반환할 값' 
        WHEN '비교할 조건2' THEN '반환할 값2' 
        ELSE '그밖의 조건으로 반환할 값' 
  END

 

참조
  * http://sarc.io/index.php/mariadb/605-dbms-migration-oracle-to-mysql-mariadb
  * http://blog.naver.com/PostView.nhn?blogId=sensate1024&logNo=220439813849&parentCategoryNo=&categoryNo=75&viewDate=&isShowPopularPosts=true&from=search
  * http://www.sqlines.com/oracle-to-mariadb ==> Open Source Tool



1. 기본적인 차이에 대한 이해

  * Oracle : Multi-process 방식
  * MySQL : Single-process, Multi-thread  방식
 
2. 메타데이터

  * MySQL :  사용자 인증 정보, 스토어드 프로그램, 이벤트 정보, 복제 관련 정보
     ex) mysql.user
  * INFORMATION_SCHEMA : 메모리 내의 메타 정보를 테이블 형태로 접근할 수 있다.
     ex) information_schema.tables, information_schema.innodb_trx
  * PERFORMANCE_SCHEMA : MySQL 서버가 쿼리 처리 시 발생하는 각종 이벤트 및 잠금 현상 등을 숫자로 기억하는 테이블 저장 공간

 3. SQL 전환

  * 타입
    - NUMBER -> INT
    - VARCHAR2 -> VARCHAR
    - DATE -> DATETIME (참고로 SQL Server도 DATETIME)
 
  * 함수
    - NVL -> IFNULL
      ex) SELECT IFNULL(LAST_IP,'XXX') FROM CO_CD_ITEMCD_0;

    - NVL2(expr, expr1, expr2) -> CASE
      - expr의 값이 null이 아닐 경우 expr1값 리턴, null 인경우 expr2 리턴
      ex) Oracle: SELECT NVL2(MENU_ID, 'Y','N') AS NVL2 FROM MENU ;
            MariaDB: SELECT CASE
                                  WHEN MENU_ID IS NULL THEN 'N'
                                  ELSE 'Y'
                              END AS NVL2
                            FROM MENU

    - SYSDATE -> NOW()
      ex) Oracle: SELECT SYSDATE FROM DUAL;
            MariaDB: SELECT NOW(); 또는 SELECT SYSDATE();

    - TRUNC -> CURDATE, MySQL에서 TRUNC 하면 시간이 없는 일자만 나옴.
      ex) Oracle: SELECT TRUNC(SYSDATE) FROM DUAL;
            MariaDB: SELECT CURDATE() ;

    - DECODE -> CASE

    - TO_NUMBER -> CAST

    - CAST
      - CAST('' AS VARCHAR(1)) 사용 불가
      - CAST('' AS CHAR) 수정

    - DECODE()
      - MariaDB에서 DECODE는 암호화 예약어로 쓰임
      - CASE문으로 대체해서 사용해야 함
 
  * 시퀀스
    - 지원하지 않는다. 직접 함수를 만들어 사용해야 한다.
      - 혹은 AUTO_INCREMENT 속성 컬럼 사용
    - MariaDB 10.3 이후 지원
      - CREATE, ALTER SEQUENCE statements


Oracle MariaDB
1 CREATE SEQUENCE seqname CREATE [OR REPLACE] SEQUENCE seqname
2 ALTER SEQUENCE seqname ALTER SEQUENCE [IF EXISTS] seqname
3 INCREMENT BY num Positive or negative increment, default is 1 INCREMENT BY num
4 START WITH num Initial value START WITH num
5 MAXVALUE num Maximum value is num MAXVALUE num
NOMAXVALUE System limit NOMAXVALUE
6 MINVALUE num Minimum value is num MINVALUE num
NOMINVALUE System limit NOMINVALUE
7 CYCLE Reuse values after reaching the limit CYCLE
NOCYCLE No reuse, this is default NOCYCLE
8 CACHE num Cache num values, default is 20 CACHE num Default is 1000
NOCACHE Values are not preallocated NOCACHE
9 ORDER Guarantee numbers in order of requests Option not supported, commented
NOORDER No guarantee, this is default Option not supported, removed as it is default

      - Referencing sequence values:


Oracle MariaDB
1 seqname.CURRVAL The current value of seqname NEXTVAL(seqname) NEXT VALUE FOR seqname
2 seqname.NEXTVAL The next value of seqname LASTVAL(seqname) PREVIOUS VALUE FOR seqname


      - DROP SEQUENCE statements:
 


Oracle MariaDB
1 DROP SEQUENCE seqname DROP SEQUENCE [IF EXISTS] seqname


 * 힌트
    - 다 지운다. 있어도 무시된다.
 
 * rownum
    - 조건에 rownum을 사용하고 있던 경우는 limit으로 대체

      SELECT * FROM ${TABLE_NAME} LIMIT 4,10;
      해석: 5번째 레코드부터 10개의 결과 추출, 시작이 0임에 유의하자.
 
  * 날짜 관련
    - TO_CHAR -> DATE_FORMAT()
      - DATE_FORMAT(): 데이터형을 문자로 변환
        ex) Oracle: SELECT TO_CHAR(SYSDATE, 'MMDDYYYYHH24MISS')
                         FROM DUAL ;
              MariaDB: SELECT DATE_FORMAT(now(),'%m%d%Y%H%i%s') ;
       ( '%Y%m%d' 대소문자 주의!!! Y는 4자리, y는 2자리, %m은 12기준 %M은 24기준 )
       ( now()함수는 SYSDATE()함수로도 사용가능 )
        ex) TO_CHAR(SYSDATE, 'YYYYMMDD') -> DATE_FORMAT(NOW(), '%Y%d%m')
      - LPAD(): 숫자를 문자로 변환하고 앞자리 공백대신 문자넣기
        ex) Oracle: SELECT TO_CHAR(1, 'FM00') FROM DUAL;
              MariaDB : SELECT LPAD(1, 2, '0') ;
              -> LPAD()함수는 오라클과 사용방법이 동일하다.

    - TO_DATE() -> STR_TO_DATE()
      ex) Oracle: SELECT TO_DATE('10/30/2012 00:00:00'
                                            , 'MM/DD/YYYYHH24:MI:SS')
                      FROM DUAL ;
            MariaDB: SELECT STR_TO_DATE('10/30/2012 00:00:00'                                                   , '%m/%d/%Y %H:%i:%s') ;
 
  * MERGE INTO
    - 쿼리문을 풀어서 수행한다.

  * START WITH CONNECT BY
    - WITH문을 이용한 RECURSIVE 쿼리로 변경
 
  * 서브쿼리
    - 서브쿼리에 alias가 없다면 붙여야 한다.
 
  * DELETE
    - DELETE [테이블명]으로 쓰이고 있는 부분이 있다면 DELETE FROM [테이블명] 으로 수정해야 한다.
 
  * OUTER JOIN
    - (참고) OUTER JOIN은 INNER JOIN을 확장한 것으로 공통 컬럼 값이 NULL이더라도 조회 결과에 포함된다.
    - MySQL에서는 LEFT OUTER JOIN ... ON, RIGHT OUTER JOIN ... ON 과 같이 ANSI SQL 타입으로 표기해야 한다.

1) LEFT OUTER JOIN
SELECT A.*, B.* FROM A, B WHERE A.ID = B.ID(+);
    - 다음과 같이 변경한다.
SELECT A.*, B.* FROM A LEFT OUTER JOIN B ON A.ID = B.ID;
2) RIGHT OUTER JOIN
SELECT A.*, B.* FROM A, B WHERE A.ID(+) = B.ID;
    - 다음과 같이 변경한다.
SELECT A.*, B.* FROM A RIGHT OUTER JOIN B ON A.ID = B.ID;
 
  * 테이블 확인
    - Oracle은 다음과 같이 사용한다.
SELECT COUNT(*) TABLE_COUNT FROM ALL_TABLES WHERE TABLE_NAME = [테이블명]
    - MySQL에서는 다음과 같다.
SELECT COUNT(*) TABLE_COUNT FROM information_schema.tables
WHERE table_schema = [DB명] AND table_name = [테이블명]

 

 

Oracle쿼리문을 MySQL쿼리로 변환 방법
[출처] Oracle쿼리문을 MySQL쿼리로 변환 방법|작성자 강철고양이





1. NVL 함수를  IFNULL 함수로 변경한다.  

2. SYSDATE 함수를 NOW() 함수로 변경한다.  

3. trunc(sysdate)를 하면 시간만 잘린 일자가 나온다.  
MySQL에서 날자만 반환해주는 CURDATE()를 쓴다.

4. Sequence는 사용자 함수를 만들어 사용한다.
사용자 함수 만드는 방법
http://blog.naver.com/steelcatx/60184547400

SELECT zon_sq01.nextval FROM dual; -> SELECT get_next_seq_val('zon_sq01') FROM dual;
SELECT zon_sq01.currval FROM dual; -> SELECT get_curr_seq_val('zon_sq01') FROM dual;

sequence 추가가 필요할시 mysql_seq_table에 seq_nm(시퀀스명), last_cached_val(마지막 사용된 값)를 입력한다.

5. 인덱스 힌트 제거한다. 
있더라도 큰 영향 없으므로 대상에서 제외

6. Date 함수 관련  
6-1. TO_CHAR()를 DATE_FORMAT()으로 변환한다.
TO_CHAR(sysdate,'MMDDYYYYHH24MISS')의 경우
DATE_FORMAT(now(),'%m%d%Y%H%i%s')로 변환 -- '%Y%m%d' 대소문자 주의!!! Y는 4자리, y는 2자리, %m은 12기준 %M은 24기준

6-2. 요일 변경
자바스크립트의 요일은(0-6), MySQL의 요일은(0-6), ORACLE의 요일은(1,7)
그러므로 자바스크립트와 oracle의 요일차이로 TO_CHAR(SYSDATE-1, 'D')를 
그대로 변경 시키면 아래구문이지만 
=> DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 DAY), '%w')

MySQL에서는 -1을 할 필요가 없으므로 
=> DATE_FORMAT(NOW(), '%w')

6-3. TO_DATE()를 STR_TO_DATE()으로 변환한다.
TO_DATE('10/30/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS')의 경우 
=> STR_TO_DATE('10/30/2012 00:00:00', '%m/%d/%Y %H:%i:%s')로 변환

TRUNC(to_date('20130227', 'YYYYMMDD')+30) 의 경우
=> DATE_ADD(str_to_date('20130227', '%Y%m%d'), INTERVAL 30 DAY) -- '%Y%m%d' 대소문자 주의!!! Y는 4자리, y는 2자리, %m은 12기준 %M은 24기준

6-4. 날짜 가감 
oracle은 날짜형 데이터에 +1을 하면 1일이 추가되나 mysql은 이상하게 변함.
sysdate + 1
=> DATE_ADD(now(), interval 1 DAY)

DATE_ADD(date,INTERVAL expr  unit) -- 날짜 가산
DATE_SUB(date,INTERVAL expr  unit) -- 날짜 감산
DATE_ADD, DATE_SUB를 사용 할 경우 '0000-00-00 00:00:00'나 '0000/00/00 00:00:00'의 형태만 맞춰 주면 문자도 자동으로 변경하여 연산됨.

unit Value  expr 형태  
MICROSECOND  MICROSECONDS
SECOND   SECONDS
MINUTE   MINUTES
HOUR   HOURS
DAY   DAYS
WEEK   WEEKS
MONTH   MONTHS
QUARTER   QUARTERS
YEAR   YEARS
SECOND_MICROSECOND 'SECONDS.MICROSECONDS'
MINUTE_MICROSECOND 'MINUTES:SECONDS.MICROSECONDS'
MINUTE_SECOND  'MINUTES:SECONDS'
HOUR_MICROSECOND 'HOURS:MINUTES:SECONDS.MICROSECONDS'
HOUR_SECOND  'HOURS:MINUTES:SECONDS'
HOUR_MINUTE  'HOURS:MINUTES'
DAY_MICROSECOND  'DAYS HOURS:MINUTES:SECONDS.MICROSECONDS'
DAY_SECOND  'DAYS HOURS:MINUTES:SECONDS'
DAY_MINUTE  'DAYS HOURS:MINUTES'
DAY_HOUR  'DAYS HOURS'
YEAR_MONTH  'YEARS-MONTHS'

예)
SELECT DATE_ADD('1900-01-01 00:00:00', INTERVAL '-1 10' DAY_HOUR); 
-> '1899-12-30 14:00:00' -- 34시간이 감산됨
SELECT DATE_ADD('1900-01-01 00:00:00', INTERVAL '1 -10' DAY_HOUR); 
-> '1900-01-02 10:00:00' -- 34시간이 가산됨

6-5. 날짜와 날짜의 차이 구하기
SELECT to_date('20130314', 'YYYYMMDD')- to_date('20130313', 'YYYYMMDD') FROM DUAL -- 1일 이 조회됨
-> SELECT TO_DAYS(str_to_date('20130314', '%Y%m%d'))- TO_DAYS(str_to_date('20130313', '%Y%m%d')) FROM DUAL


7. Outerjoin 변경 
[Oracle]
left outer joing : SELECT t1.*, t2.* FROM t1, t2 where t1.i1 = t2.i2(+);
right outer joing: SELECT t1.*, t2.* FROM t1, t2 where t1.i1(+) = t2.i2; 

[MySQL] 
left outer joing : SELECT t1.*, t2.* FROM t1 LEFT OUTER JOIN t2 ON t1.i1 = t2.i2;
right outer joing: SELECT t1.*, t2.* FROM t1 RIGHT OUTER JOIN t2 ON t1.i1 = t2.i2;

% From절에서 테이블명 중간에 , 가 없다는것과 ON 구문이 From절 바로 뒤에 오게 
해야하는것에 주의 

8. rownum 변환
8-1. rownum이 조건으로 사용될 경우 limit를 사용
rownum >= 5 와 rownum <= 10 이면 limit 4, 5
ex) 리스트 페이징에서 11번째부터 20번째까지 limit 10, 10
처음부터 10개  ... LIMIT 10
5번째부터 10개  ... LIMIT 4, 10
5번째부터 마지막까지 ... LIMIT 4, -1

이때 주의 할 점은 첫번째 레코드의 시작은 “0”
즉 “LIMIT 1, 3 - 2번째부터 3개” 의 결과를 출력
예)
select * from table LIMIT 1, 3;
8-2. rownum이 컬럼으로 사용될 경우 변수 사용
select @rownum := @rownum + 1 as rownum
, table.* 
from table
JOIN (select @rownum := 0) r;
8-3. rownum이 조건 및 컬럼으로 모두 사용될 경우 2.를 적용한 서브쿼리로 작성
select *
from (
select @rownum := @rownum + 1 as rownum
, table.* 
from table
JOIN (select @rownum := 0) r
)
where rownum < 3;

9. Subquery에서 alias가 없다면 붙인다.  
select a, b from ( select a, b from ttt)  
--> select t.a, t.b from ( select a, b from ttt) t

10. DELETE 테이블명 쿼리문을 DELETE FROM 테이블명 쿼리문으로 바꾸어준다. 
oracle에서는 FROM을 생략해도 되지만 MySQL에서는 반드시 필요

11. Merge into의 경우는 쿼리문을 분리하여 처리로직으로 변경해준다. 
변경방법은 아래 두가지중에 하나를 선택해도 되고 다른 방법을 써도 된다.
11-1 조건이 맞는지(MATCHED)에 대한 SELECT문을 실행시켜서 결과값이 있으면 UPDATE문을 실행시켜 주고 결과값이 없으면 INSERT문을 실행시켜준다.

11-2 UPDATE문을 실행해서 UPDATE가 일어나면 그대로 가고 UPDATE가 일어나지 않으면 INSERT문을 실행시킨다. 

12. decode문 case로 변경
decode( 1,1,'true','false') -> case when 1=1 then 'true' else 'false' end

13. start with connet by 문은 with를 사용한 recursive 쿼리로 변경 
recursive 쿼리 작성 방법
http://blog.naver.com/steelcatx/60186185102

14. mysql은 대소문자 구분함. 모든 컬럼명과 테이블명의 대소문자 확인 

15. 오라클의 ||(Vertical Bar) 사용할 수없음. CONCAT으로 변경
TO_CHAR(NOW(), 'yymmdd') || LPAD(get_next_seq_val('ord_cl_info_sq01'), 9, '0')
--> CONCAT(DATE_FORMAT(NOW(), '%y%m%d') ,LPAD(get_next_seq_val('ord_cl_info_sq01'), 9, '0'))

16. TO_CHAR, TO_NUMBER -> CAST로 변경 
SELECT TO_CHAR( 11 ) AS AA FROM DUAL
--> SELECT CAST( 11 AS CHAR ) AS AA FROM DUAL
SELECT TO_NUMBER( '-11' ) AS AA FROM DUAL
--> SELECT CAST( '-11' AS SIGNED ) AS AA FROM DUAL


출처: https://stepping.tistory.com/22?category=691571 [디딤돌]
And

Tomcat 프로세스 강제종료

|

Windows
시작 - 실행 - cmd
커맨드라인에 netstat -ao 실행 후 톰캣이 사용중인 포트의 PID를 찾는다

C:\>netstat -ao

Active Connections

  Proto  Local Address                               Foreign Address             State               PID
  TCP    LENOVO-B24A7D1F:epmap          LENOVO-B24A7D1F:0      LISTENING       1580
  TCP    LENOVO-B24A7D1F:microsoft-ds  LENOVO-B24A7D1F:0      LISTENING       4
  TCP    LENOVO-B24A7D1F:3306              LENOVO-B24A7D1F:0      LISTENING       2776
  TCP    LENOVO-B24A7D1F:6004              LENOVO-B24A7D1F:0      LISTENING       1304
  TCP    LENOVO-B24A7D1F:6060              LENOVO-B24A7D1F:0      LISTENING       3148
  TCP    LENOVO-B24A7D1F:8009              LENOVO-B24A7D1F:0      LISTENING       780
  TCP  LENOVO-B24A7D1F:8080       LENOVO-B24A7D1F:0  LISTENING    780
  TCP    LENOVO-B24A7D1F:50313             LENOVO-B24A7D1F:0      LISTENING       3432


8080포트를 사용중인 톰캣의 PID는 780 이라는 것을 알 수있다..
윈도우의 작업관리자에서 780번의 PID를 찾아 강제종료 혹은 cmd창에서 taskkill /f /pid 프로세스아이디


Linux

[root@memobook]# ps -ef | grep tomcat

UID       PID     PPID   C   STIME  TTY     TIME      CMD
root      9093      1        0   2010       ?        14:57:59   /usr/local/share/jdk1.6.0_16/bin/java ... 생략
root     12325     12287  0  13:58      pts/0   00:00:00   grep tomcat

[root@memobook]# kill -9 9093


ps 명령어로 현재 실행중인 프로세스 중, tomcat의 프로세스를 찾은 후,
kill 명령어로 강제종료



출처: https://blog.t-that.com/entry/Tomcat-프로세스-강제종료 [이것저것 This That]

'DevTools' 카테고리의 다른 글

Tomcat context 설정  (0) 2020.04.02
UML - 관련 정리  (0) 2020.03.30
전자정부프레임워크  (0) 2020.02.06
Server에서 Tomcat 클린하기  (0) 2020.01.08
Maven 설치, Jenkins 설치  (0) 2019.10.14
And

객체 얕은 복사(shallow copy)와 깊은 복사(deep copy)

|

tring형태의 데이터, Boolean형태의 데이터, Number 데이터는 순수한 값이기 때문에 복사를 했을때 순수한 값이 복사가 되고 독립적인 값이 저장이 된다.

 

// Number와 Boolean형태도 동일하게 순수한 값이 복사가 된다.
var original = '원본';
var copy = original;
console.log('copy의 값은?', copy); // 원본
    
copy = '복제품';
console.log('original의 값은?', original); // 원본
console.log('copy의 값은?', copy); // 복제품

 

객체는 조금 다르다. 위의 데이터 복사 방식대로 복사를 했을때 Js의 객체는 얕은복사(shallow copy)가 수행된다.

// 원본
var original = ['원본'];
console.log('original의 0번 인덱스의 값은?', original[0]); // 원본
 
// 복사
var copy = original;
console.log('copy의 0번 인덱스의 값은?', copy[0]); // 원본
 
// 복사의 값 변경시 원본도 영향을 받음
copy[0] = '복제품';
console.log('original의 0번 인덱스의 값은?', original[0]); // 복제품
console.log('copy의 0번 인덱스의 값은?', copy[0]); // 복제품


copy는 현재 original의 값을 바라보고 있을 뿐 실제 original의 값을 복사한것이 아니다.

값을 복사하는것이 아닌 지정한 값의 레퍼런스를 참조하는 복제를 얕은복사(shallow copy)라고 한다. (복사 하겠다! 보다는 참조하겠다!로 보면된다.)

 

 

String,Number,Boolean의 값을 복사할때처럼 순수 값을 복사하려면 깊은복사(deep copy)를 수행해야한다. deep copy를 수행하는 방법은 여러가지가 있지만 여기서는 JSON.parse와 JSON.stringify를 활용하는 방법을 소개하려고 한다. 우선 예제 코드를 보자

var original = ['원본'];
console.log('original의 0번 인덱스의 값은?', original[0]); // 원본
 
var copy = JSON.parse(JSON.stringify(original));
console.log('copy의 0번 인덱스의 값은?', copy[0]); // 원본
 
copy[0] = '복제품';
console.log('original의 0번 인덱스의 값은?', original[0]); // 원본
console.log('copy의 0번 인덱스의 값은?', copy[0]); // 복제품

위의 예제와 달라진점은 copy를 복사하는 과정에서 original의 값을 JSON.parse(JSON.stringify(original))의 형태로 받아왔다.

 

deep copy를 수행하면 레퍼런스의 데이터 자체를 복사하기 때문에 copy 객체를 수정하더라도 원본 객체와는 별도의 값이 수정이된다. 참조 레퍼런스의 순수한 값을 복사하는것을 깊은복사(deep copy)라고 한다.

 

2018.06.08 추가
JSON방식으로 Deep copy를 수행했을때 Date형식의 데이터는 JSON 형태로 변환되어 값으로써 복사되는 현상을 발견하였음 date 형태로 deep copy를 수행할때는 다른 방법을 사용하자 

 

출처 :

http://hong.adfeel.info/frontend/javascript-%EA%B0%9D%EC%B2%B4-deep-copy/

'JavaScript' 카테고리의 다른 글

클래스 기반 언어 vs 자바스크립트  (0) 2020.03.27
Function, Method, Property 의 차이 및 정의  (0) 2020.03.25
호이스팅(Hoisting)  (0) 2020.01.21
JSON  (0) 2020.01.12
변수 선언 방법  (0) 2020.01.12
And

이력 테이블에서 최종 데이터만 조회하기

|

현재 상태와 이력을 별개의 테이블로 관리하는 곳도 있지만

둘을 분리하지 않고 이력테이블에서 최종 데이터를 읽어오도록 설계하는 곳도 꽤나 많다

 

이럴 경우에는 그동안 아래와 같이 쿼리를 짜곤했다.

 

SELECT 원하는 컬럼들...

FROM 테이블명

WHERE (키값, 최종이력날짜) IN (SELECT 키값, MAX(이력날짜)

                                     FROM 테이블명

                                     GROUP BY 키값)

 

IN 을 쓰든 EXISTS를 쓰던 그건 테이블의 데이터 크기나 구조에 따라서 달라질 수는 있지만

아무튼 최종 데이터를 읽으려면 위와 같이 쓰는 수밖에 없었다.

 

이 부분을 해결한게 있으니 바로 KEEP DENSE_RANK LAST (혹은 FIRST) 이다.

 

위와 똑같은 쿼리를 KEEP DENSE_RANK LAST를 쓰게 되면 아래와 같다.

SELECT MAX(컬럼1) KEEP (DENSE_RANK LAST ORDER BY 이력날짜),

         MAX(컬럼2) KEEP (DENSE_RANK LAST ORDER BY 이력날짜), 

         MAX(컬럼3) KEEP (DENSE_RANK LAST ORDER BY 이력날짜)

         .....

FROM 테이블명

GROUP BY 키값;

 

예제를 들어 설명해보자면 아래와 같다

 

사원들이 사무실을 출입할때마다 카드를 찍고 해당 이력이 EMP_ENTER_HIST라는 테이블에 쌓는다.

사원번호 (EMP_NO)

출입구분(ENTER_IND)

 이력시간 (HIST_TIME)

00251

 입실

 2015.02.25 09:00

00251

 퇴실

 2015.02.25 11:30

00251

 입실

 2015.02.25 12.03

00588

 입실

 2015.02.25 08:30 

00588

 퇴실 

 2015.02.25 13:40

00012

 입실 

 2015.02.25 08:00 

 

위와 같이 데이터가 쌓이고 있을때

사원별로 누가 재실해있고 누가 퇴실했는지를 확인하고자 한다면 아래와 같이 쿼리를 날린다.

 

SELECT MAX(ENTER_IND) KEEP (DENSE_RANK LAST ORDER BY HIST_TIME)

FROM EMP_ENTER_HIST

GROUP BY EMP_NO

;

 

그 결과값은 아래와 같이 나온다.

 

 

사원번호 출입구분
00251 입실
00588 퇴실
00012 입실

 

[출처] 이력 테이블에서 최종 데이터만 조회하기|작성자 깽이

And

CSS기본문법, 속성, 선택자

|

 

----------------CSS를 사용하는 방법 - style 태그 or 속성 사용----------------------
CSS(Cascading Style Sheets)

<style>
a {   			// 모든 'a'태그에 대해서 - Selector(선택자) - a태그
color: red;		// '빨간색'으로 바꿔라 - Declaration(선언) - 선택자가 지정하는 태그들에 대해서 어떠한 효과를 줄 것인가
text-align: center; // 글자정렬 가운데
text-decoration : none; // 모든 꾸밈 없애라
}
</style>

Property(속성) - color
Value(속성의 값) - red

'css text size property' -> 구글검색해서 스스로 알아낼수있음.


----------------------선택자------------------------------------
class (.)
- 의도: 하나로 묶는다. Grouping.(ex. .saw{~} : "saw"라는 클래스를 모두 ~로 바꾼다.)
- class property에는 여러개의 value가 들어올 수 있고 띄어쓰기로 구분한다
- 여러 class selector로 하나의 tag를 공동으로 제어할 수 있다 BUT
- 순서에 따라 priority is changed. The latest one is valid. Therefore, we use id


id (#)
- value가 단 하나만 등장해야한다. 중복되어서는 안된다. Only one value, can not be repeated.
- 유일무이.

<selector's priority>
- id>class>tag 
- 좀더 포괄적인 것이 우선순위 나중.
- 좀더 구체적인 것이 우선순위 우선.

선택자A, 선택자B
- 후손 선택자, 특정한 태그 아래에 있는 모든 후손을 선택

선택자A > 선택자B
- 자손 선택자, 바로 아래에 있는 자손을 선택할 때 싸용

선택자A + 선택자B
- 동위선택자, 바로 두의 선택자

선택자A ~ 선택자B
- 선택자A 뒤에 위치하는 모든선택자B를 선택

Selector(선택자)
Declaration(선언)-선택자가 지정하는 태그들에 대해서 어떠한 효과를 줄 것인가
Property(속성)
Value(속성의 값)

And