2018년 5월 24일 목요일

스택트레이스(stacktrace) 읽는 팁

자바는 에러 발생시 익셉션을 발생시켜서 에러가 발생한 위치를 정확히 알려준다.

스택트레이스는 꽤나 중요한 사항인데, 나 역시도 깊게 생각해 본 적이 없다.

그러다 okky 글을 읽고 내 나름의 스택트레이스 읽는 팁을 적어 본다.

 
1. lib 는 제외하고, 내 소스 부분만 본다.

2. 스택의 제일 윗 부분을 본다.

3. Caused by 가 있을 경우 제일 하단의 Caused by 부터 본다.

대부분의 경험있는 개발자라면 느낄 것이다. lib에서 에러가 발생하는 경우는 99%이상 없다고 본다.
에러의 대부분은 내가 짠 소스에서 발생한다.
개발할 때는 기본적으로 여러가지 라이브러리를 사용하기 때문에 스택이 복잡해 지는 데, 라이브러리를 제외하고 보면 꽤나 단순해 진다.

스택은 알다시피 First in Last Out (FILO)이다. 그렇기 때문에 제일 상단의 라인이 제일 마지막에 실행된 부분이고 이 부분이 에러인 경우가 가장 많다.

"Caused by: " 부분은 exception chaining 이 발생 할 때 나타나는 메시지이다.
제일 하단의 "Caused by: " 섹션에서 내 패키지가 없다면 패스, 있다면 해당 부분이 원인일 경우가 많다.

검색해 보니, 이런 부분을 이용하여 보기 스택트레이스를 보기 좋게 해주는 사이트도 있다.

참조
https://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors
https://bukkit.org/threads/how-to-read-stack-traces-and-troubleshoot-your-own-plugins-by-yourself.32457/

2018년 2월 10일 토요일

Parameter index out of range (3 > number of parameters, which is 2)

mybatis 사용시 아래와 같은 에러 발생.

Parameter index out of range (3 > number of parameters, which is 2)

원인은 mybatis 변수 사용시 '를 사용하였기 때문이였다.
#before
AND reg_date BETWEEN CONCAT('#{start_search_date}', ' 00:00:00') AND CONCAT('#{end_search_date}',' 23:59:59')

#after
AND reg_date BETWEEN CONCAT(#{start_search_date}, ' 00:00:00') AND CONCAT(#{end_search_date},' 23:59:59')

 

 

2017년 12월 26일 화요일

Mysql 암호화, 복호화

 
#암호화
INSERT INTO 테이블명 (컬럼1) VALUES (HEX(AES_ENCRYPT('문자열', SHA2('My secret passphrase',512))));

#복호화
SELECT CAST(AES_DECRYPT(UNHEX(컬럼1), SHA2('My secret passphrase',512)) as char) FROM 테이블명;
OR
#복호화
SELECT CONVERT(AES_DECRYPT(UNHEX(컬럼1), SHA2('My secret passphrase',512)) USING utf8) FROM 테이블명;

 

CAST나 CONVERT으로 형변환 하는 부분 때문에 한참 해맸다.
대부분의 블로그가 형변환을 안 써 놨다.(심지어 공식 사이트 에서도...)

암복호화 함수의 리턴값은 BINARY 이기 때문에 HEX를 사용하지 않으면 필드 타입을 BINARY 저장이 가능한 타입으로 지정해야 된다. 공식문서는 BLOB을 추천한다고...

문제는 BINARY타입으로 지정시 일반 문자열 저장이 안되는 문제가 있기 때문에 필드타입을 VARCAHR로 사용하고 HEX를 사용하여 저장이 가능 하도록 한다.

 

MySQL 5.6이상부터 변경 가능.
암호화 모드 확인
select @@block_encryption_mode

암호화 모드 변경
SET block_encryption_mode = 'aes-256-cbc';#기본값 aes-128-ecb

암호화 모도는 처음부터 확인. 중간에 바뀌면 골치 아파진다.

2017년 12월 18일 월요일

svnadmin: E140001: 잘못된 덤프 파일 헤더

svnadmin: E140001: 잘못된 덤프 파일 헤더

윈도우에 설치된 visualsvn 에서
리눅스 svnserve로 옮기려고 할 때
발생하는 에러이다.

원인은 인코딩 문제라고 한다.
왜 이런 에러가 나냐면 command로 덤프 파일을 생성하지 않고,
Repository 의 우측 클릭 후 Backup Repository로 덤프를 생성하였기 때문이다.

command로 덤프를 생성하면 linux svnserve에서 에러 없이 제대로 올라 간다.

2017년 11월 30일 목요일

mybatis List객체에 제대로 select 데이터를 못 가져오는 경우.

기본적으로 mybatis 사용시 select 데이터는 아래와 같이 리스트로 받는다.

List<ConfirmingReceiptT> result2 = service.selectListConfirmingReceiptT(map);



이걸 객체에 List 변수로 받고자 하면 아래와 같이 한다.
public class GetConfirmingReceiptListResponseT {

@XmlElement(name = "ConfirmingReceipt")
protected List<ConfirmingReceiptT> confirmingReceipt;
...



여기서 문제가 발생.
최상위 객체인 GetConfirmingReceiptListResponseT의 confirmingReceipt에 내용이 담기지 않는 문제가 발생.

대략 일주일 정도 삽질 한 결과 최상위 객체에 달랑 List 변수 하나만 있으면 mybatis가
이걸 인식을 못한다.

해결책은 필요는 없지만 result를 한개더 추가 해 준다.

해결한 resultMap
<resultMap type="kr.co.auction.schema.arche_apisvc.ConfirmingReceiptT" id="ConfirmingReceiptT">
  <result property="receiptStatus" column="receiptStatus" />
  <result property="sellingType" column="SELLINGTYPE" />
  <result property="paymentTimeLimit" column="paymentTimeLimit" />
  <association property="orderBase" javaType="kr.co.auction.schema.arche_apisvc.OrderBaseT" >
   <id property="itemID" column="itemID" />
   <result property="orderNo" column="orderNo" />
   <result property="itemName" column="itemName" />
   <result property="awardQty" column="awardQty" />
   <result property="awardAmount" column="awardAmount" />
   <result property="deliveryFeeAmount" column="deliveryFeeAmount" />
   <result property="buyerName" column="buyerName" />
   <result property="buyerID" column="buyerID" />
   <result property="groupOrderSeqno" column="groupOrderSeqno" />
   <result property="requestOption" column="requestOption" />
   <result property="requestOptionPrice" column="requestOptionPrice" />
   <result property="sellerStockCode" column="sellerStockCode" />
   <result property="orderDate" column="orderDate" />
  </association>
  <association property="addressBase" javaType="kr.co.auction.schema.arche_apisvc.AddressBaseT" >
   <result property="name" column="name" />
   <result property="tel" column="tel" />
   <result property="mobileTel" column="mobileTel" />
   <result property="email" column="email" />
   <result property="postNo" column="postNo" />
   <result property="addressPost" column="addressPost" />
   <result property="addressDetail" column="addressDetail" />
   <result property="addressRoadName" column="addressRoadName" />
  </association>

</resultMap>


<resultMap type="kr.co.auction.schema.arche_apisvc.GetConfirmingReceiptListResponseT" id="GetConfirmingReceiptListResponseT" autoMapping="true">
 <result column="ADDUSERCD"  /><!-- temp, collection 한개만 있으면, List객체로 반환이 안됨. -->
 <collection property="confirmingReceipt" ofType="kr.co.auction.schema.arche_apisvc.ConfirmingReceiptT" resultMap="ConfirmingReceiptT" />
</resultMap>

2017년 11월 28일 화요일

mybatis 에서 association를 사용하면 중복 제거 문제.

mybatis 에서 association를 사용하면 중복된 값이 출력되지 않는 문제가 있다.
<resultMap type="kr.co.auction.schema.arche_apisvc.ConfirmingReceiptT" id="ConfirmingReceiptT" >
  <result property="receiptStatus" column="RECEIPTSTATUS" />
  <result property="sellingType" column="SELLINGTYPE" />
  <result property="paymentTimeLimit" column="PAYMENTTIMELIMIT" />
  <association property="orderBase" javaType="kr.co.auction.schema.arche_apisvc.OrderBaseT" >
   <result property="itemID" column="ITEMID" />
   <result property="orderNo" column="ORDERNO" />
   <result property="itemName" column="ITEMNAME" />
   <result property="awardQty" column="AWARDQTY" />
   <result property="awardAmount" column="AWARDAMOUNT" />
   <result property="deliveryFeeAmount" column="DELIVERYFEEAMOUNT" />
   <result property="buyerName" column="BUYERNAME" />
   <result property="buyerID" column="BUYERID" />
   <result property="groupOrderSeqno" column="GROUPORDERSEQNO" />
   <result property="requestOption" column="REQUESTOPTION" />
   <result property="requestOptionPrice" column="REQUESTOPTIONPRICE" />
   <result property="sellerStockCode" column="SELLERSTOCKCODE" />
   <result property="orderDate" column="ORDERDATE" />
  </association>
  <association property="addressBase" javaType="kr.co.auction.schema.arche_apisvc.AddressBaseT" >
   <result property="name" column="NAME" />
   <result property="tel" column="TEL" />
   <result property="mobileTel" column="MOBILETEL" />
   <result property="email" column="EMAIL" />
   <result property="postNo" column="POSTNO" />
   <result property="addressPost" column="ADDRESSPOST" />
   <result property="addressDetail" column="ADDRESSDETAIL" />
   <result property="addressRoadName" column="ADDRESSROADNAME" />
  </association>

</resultMap>

예를 들어 위와 같은 resultMap이 있을 경우, RECEIPTSTATUS, SELLINGTYPE, PAYMENTTIMELIMIT 3개의 필드의 내용이 모두 같을 경우는 총 row가 10개든, 100개든 한개의 row만 출력된다.

검색하면 <result 를 <id 로 바꾸라는 내용이 있는데, 이건 중복체크에 사용할 필드를 지정하는 것이다. <id로 지정시에는 해당 필드만 중복체크에 사용한다.

<result를 사용하면 나처럼 모두 비교한다.
나의 경우는 id 역할을 하는 필드(ex.primari key)가 없어서 문제가 된다.

해결책은 여기서 찾았다.
association을 쓰지 말라는 거다.
어떻게 보면 더 깔끔한 것 같기도 하다.
아무튼 아래와 같이 변경하면 중복된 내용을 제외하고 않고 전체를 잘 가져온다.
<resultMap type="kr.co.auction.schema.arche_apisvc.ConfirmingReceiptT" id="ConfirmingReceiptT" >
  <result property="receiptStatus" column="RECEIPTSTATUS" />
  <result property="sellingType" column="SELLINGTYPE" />
  <result property="paymentTimeLimit" column="PAYMENTTIMELIMIT" />
  <result property="orderBase.itemID" column="ITEMID" />
  <result property="orderBase.orderNo" column="ORDERNO" />
  <result property="orderBase.itemName" column="ITEMNAME" />
  <result property="orderBase.awardQty" column="AWARDQTY" />
  <result property="orderBase.awardAmount" column="AWARDAMOUNT" />
  <result property="orderBase.deliveryFeeAmount" column="DELIVERYFEEAMOUNT" />
  <result property="orderBase.buyerName" column="BUYERNAME" />
  <result property="orderBase.buyerID" column="BUYERID" />
  <result property="orderBase.groupOrderSeqno" column="GROUPORDERSEQNO" />
  <result property="orderBase.requestOption" column="REQUESTOPTION" />
  <result property="orderBase.requestOptionPrice" column="REQUESTOPTIONPRICE" />
  <result property="orderBase.sellerStockCode" column="SELLERSTOCKCODE" />
  <result property="orderBase.orderDate" column="ORDERDATE" />
  <result property="addressBase.name" column="NAME" />
  <result property="addressBase.tel" column="TEL" />
  <result property="addressBase.mobileTel" column="MOBILETEL" />
  <result property="addressBase.email" column="EMAIL" />
  <result property="addressBase.postNo" column="POSTNO" />
  <result property="addressBase.addressPost" column="ADDRESSPOST" />
  <result property="addressBase.addressDetail" column="ADDRESSDETAIL" />
  <result property="addressBase.addressRoadName" column="ADDRESSROADNAME" />

</resultMap>

2017년 11월 24일 금요일

리눅스 ls 자주 쓰는 옵션 정리.

-l 옵션이 있어야 되는 옵션도 있고, 없어도 되는 옵션도 있지만
기본적으로 전부 붙임. 더 자세한 건 man
#디렉토리만
ls -d */
ls -l | grep `^d'

#파일만
ls -l | egrep -v '^d'


#파일 크기별 (큰 파일부터...)
ls -lS

#파일 크기별 역순(작은 파일 부터...)
ls -lSr


#일자 전체 출력
ls --full-time
ls -l --time-style=full-iso


#크기를 읽기 좋게(e.g., 1K 234M 2G)
ls -lh

#하위 디렉토리 포함
ls -lR


 

timestamp별 정렬
#접속일자 순
ls -ult

#접속일자 역순(-r 옵션이 순서를 reverse함)
ls -ultr


#변경일자 순
ls -clt

#변경일자 역순(-r 옵션이 순서를 reverse함)
ls -cltr


#수정일자 순
ls -lt

#수정일자 역순(-r 옵션이 순서를 reverse함)
ls -ltr

접속일자, 수정일자, 변경일자가 뭔지는 여기서 확인.