Mybatis시 아래와 같이 에러가 났다면 십중팔구 해당 쿼리에 세미콜론이 있는지 확인하세요.


### Cause: java.sql.SQLSyntaxErrorException: ORA-00911: 문자가 부적합합니다

; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: ORA-00911: 문자가 부적합합니다

at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:91)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:371)
at com.sun.proxy.$Proxy44.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:198)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:119)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:63)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52)

'Database' 카테고리의 다른 글

Oracle의 MERGE INTO 기초  (1) 2018.01.02
Mysql 사용자 팁  (0) 2014.12.02
Posted by 다인,보리아빠
,


얼마전 회사 동료와 AWS의 CloudFront에 대해서 이야기하다 akamai의 CDN 서비스에서 최적경로를 찾아주는 방법에 대해서 이야기를 했었다.

서로 상반되는 부분이 있어서 정확하게 집고 넘어가는 것이 좋을 것 같아서 정리합니다.

결론부터 이야기하면 대부분 기본으로 세팅을 하는게 가장 빠르다.



기본적으로 CDN서비스를 사용하면 접속하는 User에게 가장 가까운(또는 가능빠른) 서버를 알려주게 된다.

이때 가장 가까운 서버를 알려주기 위해서는 CDN은 DNS 이용한다

대부분의 경우 사용자가 별도의 설정을 하지 않고 ISP를 통해서나 DHCP서버를 통하여 DNS 정보를 받게된다.

CDN의 DNS는 실제 요청자의 IP를 알수 없다.

다만 수없이 많은 DNS의 IP만을 알수 있다. 그중에 내가 사용하는 DNS도 있을 것이다.

CDN의 DNSDNS 매핑 테이블을 관리하여 요청하는 DNS의 IP별로 최적의 IP를 내려준다.

결국 PC에 설정되어 있는 DNS의 IP별로 최적의 서버로 할당을 해주는 구조이다.

따라서 Local DNS를 엄한 곳으로(예 : 거리상으로 먼곳에 있는 DNS) 설정을 하면 엄한곳에서 가장 가까운 IP를 알려줄테니 대역폭은 몰라도 레이턴시가 좋지 않게된다.

지속적인 다운로드가 아닌 이상 일반적인 웹페이지에서는 레이턴시는 매우 중요한 요소이다.

어느 이상의 속도가 되면 대역폭은 큰의미가 없다.

레이턴시는 빠르면 빠를수록 웹페이지가 뜨게된다.



아래 이미지를 보면 대역폭(상단), 레이턴시(하단)의 성능에 따라 페이지 로딩 시간의 차이를 보여준다.

그만큼 웹서비스에서는 레이턴시가 중요하다.

구글엔지니어에게듣는 네트워킹과 웹 성능 최적화 기법 책중

http://chimera.labs.oreilly.com/books/1230000000545


우리가 크롬 브라우저로 ebay에 접속할때 domain으로 ip를 찾는 순서를 보자.

~ www.ebay.com 을 누르면 아래방법으로 순차적으로 IP를 찾아내서 실제 접속은 IP로 하게 된다.

  1. 브라우저 : 현재 caching하고 있는 DNS인지 확인한다.

  2. /etc/hosts

    • 기본적으로 /etc/hosts등에 특수한 경우에 대해서 domain과 ip를 매핑해놓는다.

    • 예 : 127.0.0.1 localhost

    • 127.0.0.1는 루프백 IP로 현재 컴퓨터를 뜻한다.

  3. resolev.conf 에 설정된 NameServer에 질의 요청을 한다.


테스트할 DNS

SK Broadband (브로드밴드) 현재 사용중인 ISP기본 DNS 서버 주소 - 210.220.163.82

KT DNS기본 DNS 서버 주소 - 168.126.63.1

Google Public (구글 퍼블릭)기본 DNS 서버 주소 - 8.8.8.8

조회된 IP별 레이턴시 비교

SKB -> round-trip min/avg/max/stddev = 3.834/5.170/7.445/1.112 ms

KT -> round-trip min/avg/max/stddev = 4.373/7.757/22.246/5.128 ms

GOOGLE - round-trip min/avg/max/stddev = 65.981/68.006/71.258/1.896 ms

정리하면

속도는 SKB -> KT -> GOOGLE 순으로 나왔다.

아마 KT 사용자였다면 KT -> SKB -> GOOGLE순으로 나왔을 것이다.

결과적으로 아카마이가 최단거리 서버를 잘 찾아준 것을 알수 있다.

실험 1 DNS에 따른 www.ebay.com 조회 결과(저는 브로드밴드사용자)

$ nslookup
> www.ebay.com
Server: 192.168.11.1
Address: 192.168.11.1#53

Non-authoritative answer:
www.ebay.com canonical name = slot9428.ebay.com.edgekey.net.
slot9428.ebay.com.edgekey.net canonical name = e9428.b.akamaiedge.net.
Name: e9428.b.akamaiedge.net
Address: 210.205.4.6

> server 168.126.63.1
Default server: 168.126.63.1
Address: 168.126.63.1#53
> www.ebay.com
Server: 168.126.63.1
Address: 168.126.63.1#53

Non-authoritative answer:
www.ebay.com canonical name = slot9428.ebay.com.edgekey.net.
slot9428.ebay.com.edgekey.net canonical name = e9428.b.akamaiedge.net.
Name: e9428.b.akamaiedge.net
Address: 104.76.90.106

> server 8.8.8.8
Default server: 8.8.8.8
Address: 8.8.8.8#53
> www.ebay.com
Server: 8.8.8.8
Address: 8.8.8.8#53

Non-authoritative answer:
www.ebay.com canonical name = slot9428.ebay.com.edgekey.net.
slot9428.ebay.com.edgekey.net canonical name = e9428.b.akamaiedge.net.
Name: e9428.b.akamaiedge.net
Address: 104.124.245.241

실험2. 조회결과별 ping 10회 테스트

해당 테스트를 통해 round-trip(레이턴시) 이곳에서 해당 목적지까지 패킷이 다녀온 시간을 잰다.


$ ping 104.76.90.106 -c10
PING 104.76.90.106 (104.76.90.106): 56 data bytes
64 bytes from 104.76.90.106: icmp_seq=0 ttl=52 time=7.281 ms
64 bytes from 104.76.90.106: icmp_seq=1 ttl=52 time=4.755 ms
64 bytes from 104.76.90.106: icmp_seq=2 ttl=52 time=5.073 ms
64 bytes from 104.76.90.106: icmp_seq=3 ttl=52 time=7.184 ms
64 bytes from 104.76.90.106: icmp_seq=4 ttl=52 time=6.049 ms
64 bytes from 104.76.90.106: icmp_seq=5 ttl=52 time=4.373 ms
64 bytes from 104.76.90.106: icmp_seq=6 ttl=52 time=10.428 ms
64 bytes from 104.76.90.106: icmp_seq=7 ttl=52 time=22.246 ms
64 bytes from 104.76.90.106: icmp_seq=8 ttl=52 time=4.593 ms
64 bytes from 104.76.90.106: icmp_seq=9 ttl=52 time=5.587 ms

--- 104.76.90.106 ping statistics ---
10 packets transmitted, 10 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 4.373/7.757/22.246/5.128 ms


$ ping 104.124.245.241 -c10
PING 104.124.245.241 (104.124.245.241): 56 data bytes
64 bytes from 104.124.245.241: icmp_seq=0 ttl=52 time=68.003 ms
64 bytes from 104.124.245.241: icmp_seq=1 ttl=52 time=67.227 ms
64 bytes from 104.124.245.241: icmp_seq=2 ttl=52 time=66.554 ms
64 bytes from 104.124.245.241: icmp_seq=3 ttl=52 time=71.258 ms
64 bytes from 104.124.245.241: icmp_seq=4 ttl=52 time=69.599 ms
64 bytes from 104.124.245.241: icmp_seq=5 ttl=52 time=67.738 ms
64 bytes from 104.124.245.241: icmp_seq=6 ttl=52 time=65.981 ms
64 bytes from 104.124.245.241: icmp_seq=7 ttl=52 time=71.142 ms
64 bytes from 104.124.245.241: icmp_seq=8 ttl=52 time=65.984 ms
64 bytes from 104.124.245.241: icmp_seq=9 ttl=52 time=66.578 ms

--- 104.124.245.241 ping statistics ---
10 packets transmitted, 10 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 65.981/68.006/71.258/1.896 ms

Posted by 다인,보리아빠
,

Mobx with angular

github : https://github.com/mobxjs/mobx-angular 정리.
정확하게 이해한건진 모르겠네...

Mobx Store

import { observable, action, autorun, reaction, computed } from 'mobx-angular';

@Injectable()
class Store {
 private init
 @observable value;
 
 constructor() { //reaction(), autorun()이 bind될 수 있도록 실행.
   this._someValue에대한추가작업(); //bind 작업
   this._값변경시실행할것(); //bind 작업.
}
 @action doSomething() { value = 'asdfasdf'; } // return 없는 action

 @computed get someValue() { //action이 있을수도 있고 return 이 있음.
   
     return value.length;
}
 private _someValue에대한추가작업() {
     //@computed method에 대해서 subscribe
     reaction(() => this.someValue, (someLength) =>{
         // someLength에 대한 처리... 언제 필요할까?
    });
}
 private _값변경시실행할것(){ //storage저장등등.
     autorun(()=>{
         //@obserable 값이 변경될때 마다 실행.
    })
}
}

@observable

관리하고자 하는 값

@computed

값 변경 X, 리턴 O (예 : getter)

computed를 통한 값변경을 위해서는 reaction을 따로 구현하여 바인딩해야함.

@action

값변경 O, 리턴 X(예 : setter 또는 조작하여 저장)

reaction() in pure private method

@computed가 발생했을때 값변경 또는 추가기능을 넣을때 사용.

autorun() in pure private method

@observable 값이 변경 될때 마다 실행 되는 trigger mehtod

컴포넌트가 처리하는 방법

changeDetection 처리

​ ChangeDetectionStrategy.onPush( 해당 components의 state가 변경되지 않는한 change detection을 하지 않는다.)

Dom Element내 처리

*mobxAutorun


<div *mobxAuthrun>
{{someMobxStore의 observable value 또는 computed method }}
</div>

​ 하위 모든 mobx observale값의 변경사항에 대해서 관찰.

*mobxReaction

​ mobxReaction으로 지정된 Method를 주시하여 해당 method 실행이 되면 화면을 갱신.


<div *mobxReaction="changeValue.bind(this)">
{{someMobxStore의 observable value 또는 computed method }}
</div>

mobx Store 어떻게 쓰면 좋을까?

Only store

데이타 저장소로만 사용.

Store File+ 전용 Service File

Store에 전용 Service를 만들어 Store를 한번 래핑해놓는다.

HTTP 통신은 전용 Service에서 구현한다.

Store + 필요한 서비스들에서 알아서 가져다가 쓰기.

필요한 서비스에서 Store 변경이 필요할 시 그때 그때 바꾼다.

Store의 값을 변경한다.

'Javascript/node.js Coding' 카테고리의 다른 글

GraphQL Overview (graphql.js server code)  (0) 2018.01.05
ES6+(EcmaScript2015+) 정리(ing)  (0) 2017.12.27
Netflix Falcor Overview  (0) 2017.12.03
Posted by 다인,보리아빠
,