[Spring Boot, Mybatis] 문제해결 : Select 해온 값의 VO객체가 null일 때


오늘은 신나는 에러의 날..인 동시에 바로바로 해결을 하는 날!

DB에서 Select해온 VO객체를 확인해보니 null로 들어오더라구요?

 

어?? 이상하다?? 해서 유심히 보니...

 


원인

DB에서는 _(언더바)를 이용해서 컬럼명을 선언했고,

VO 객체에서는 변수를 카멜케이스로 선언을 해서 생기는 문제였습니다.

생각해보니 Mybatis 설정에 _(언더바)를 camelcase로 맵핑해주는 설정을 세팅안해놨더라구요.

 

 

해결

Mybatis 설정 중 map-underscore-to-camel-case 설정 값을 true로 세팅해서 해결했습니다.

mybatis.configuration.map-underscore-to-camel-case=true

다른 해결방법으로는 VO객체의 변수를 DB와 같은 _(언더바) 형식으로 통일시켜주면 됩니다. (반대로 해도 되고..)

 예) Table의 컬럼명이 case_id라면 VO객체의 값을 받을 변수는 카멜케이스(caseId)가 아닌 컬럼명과 동일하게 case_id로 변수명을 통일해주시면 됩니다.

 


뭐 이런 초보자같은 실수만 연발하는지..

아마도 세팅을 한다고는 해도 꼭 몇몇개씩 빼먹고 진행해서 그런 것 같네요.

워낙 세팅보다는 개발에 더 많은 시간을 쓰다보니...

저번에 DB 연동할때 여러 테스트도 진행을 할 걸 그랬네요. (쩝..)

그냥 연동시켜놓고 된다! 하고 끝냈었으니... 이제와서 이런 문제가..

어쨌든 이걸로 이제 RestController에서 DB와 연동되어 받는 값들은 문제 없이 받아지고 있습니다. (아싸)

 

 

버전정보 (v1.0)

 - v1.0 2020.08.06 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com

 


[Spring Boot] 에러해결 : Invalid bound statement (not found)


 - Project.다원의 Ensemble 개발을 진행하면서 나온 문제입니다.

 

사실 어제 삼성의 언팩 행사 틀어놓고 Ensemble 개발을 진행했었는데,

블로그에 글이 안올라온 이유가 딱히 보여드릴만한게 없어서(...) 그랬습니다.. (-_-)...

에러 하나가지고 어제 오늘 잡아먹어버렸네요;; 

 

이번시간에는 해당 에러에 대한 삽질을 하며 결국 어떻게 해당 에러를 해결했는지를 적어볼까합니다.

 


 

해결을 하고보니 진짜 별 문제 아닌데 왜 이리 오래걸렸는지.. (항상 그렇죠 뭐.. 삽질 엄청하다가 해결하면 어.... 아..... 하는.. 그런거 ㅋㅋㅋ - 많은 개발자분들이 공감하지 않을까 싶네요.)

DB연동은 예~~~전에 다끝내놨는데 이제와서 Invalid bound statement (not found): ~~~ 에러가 뜨길래 뭐지? 왜 못찾지? 어디가 문제지? 하면서 열심히 찾아다녔습니다.

 

하지만 열심히 찾아봐도 뭐가 문제인지 모르겠다는 것... (결국 찾아서 해결은 했지만.)

 

원인

저의 경우 DB 연동이랑은 다 문제없이 잘 되었는데, 결국 찾은 문제는 Mapper의 xml단의 id와 interface단의 function명이 달라 생긴 문제였습니다.

당시 function명을 'getAllCode' (공통코드단에서 모든 코드를 가져오는 함수)로 해두었는데 id는 'getAllCodes'로 한 것. (ㅡ..ㅡ 지금 생각해도 s하나 못본거 때문에 삽질한걸 생각하면..)

 

 

해결

function명을 바꾸긴 귀찮아서 (이미 다른쪽에는 다 선언해서 사용중이었..) xml단의 id를 'getAllCode'로 interface와 통일해줌으로써 해결했습니다.

 


눈이 나빠져서 그런가.. (사실 안경써야하는데, 안경이 오래되어 뿌옇게 보여가지고 안쓰게되요. 아.. 안경(블루라이트 차단, 도수있는)값 너무 비쌉니다.ㅠㅠ)

그거 하나를 못 찾아서 몇 시간을 날려먹었네요.

어제 이거 해결하고 자겠다고 새벽 3시쯤 잤는데..

오늘은 시작한지 한시간(...?)걸려 해결했습니다. (하하..)

어찌되었든 끙끙거리다 해결은 되었으니, 또 다음 스탭으로의 개발로 나아갈 수 있을 것 같네요.

 

 

버전정보 (v1.0)

 - v1.0 2020.08.06 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com




Project.다원 Ensemble_기능검토(1)_QRCode (Sequence Diagram)


얼마전 저는 장비관리에 QRCode 기능을 넣을 생각을 했습니다. (Project.다원 Ensemble_개발(0)_사전 준비)

 

Project.다원 Ensemble_개발(0)_사전 준비

Project.다원 Ensemble_개발(0) 사전준비 Class Diagram을 만들기 전에 사전작업으로 개발을 위한 준비를 시작했습니다. 개발시 필요한 IDE 및 컴포넌트들을 다운받는 것이었는데, 생각보다 양이 많더라구

karzin.tistory.com

어떻게 넣을까 고민을 하며 찾아본 결과 구현 가능성이 높아졌고, 제대로된 기능검토가 필요하다고 생각이 들어서 준비했습니다!


QRCode의 생성방법 두가지

QRCode를 생성하는 방법으로 크게 잡아보자면 두가지 방법이 있습니다.

첫번째는 jQuery(Front단)를 이용해 만들어버리는거고, 두번째는 java(Back단)를 이용해 만드는 방법입니다.

둘의 차이는 서버를 경유하냐 마냐의 차이가 되겠습니다.

 

 - 1. Web-jQuery (Front)

  -> qrcodejs - (https://github.com/davidshimjs/qrcodejs)

  -> License : MIT License

  -> 장점 : 서버를 경유하지 않아 개발자인 제가 편리, 서버가 연결되지 않아도 QRCode의 생성 가능

  -> 단점 : 유저가 클릭을 할 때마다 브라우저에서는 QRCode를 만들어내야함. 

 

 - 2. Java (Back)

  -> ZXing Core - (https://github.com/zxing/zxing)

  -> License : Apache 2.0

  -> 장점 : 한번 생성을 해두고 image로 만들어두면 반복된 사용이 가능, front단의 부하를 줄일 수 있음

  -> 단점 : Java단에서 구현을 해야하고(즉, 코드의 수정이 필요한 경우 서버의 배포가 필요.), 이미지를 계속해서 관리를 해주어야함. 개발자인 제가 귀찮아짐.

 

 

그렇다면 선택은?

고민은 3초정도 했고, 결과적으로 Java소스 기반의 ZXing Core를 사용할겁니다.

서버에서 QRCode를 한번 이미지로 만들어두면 계속된 재사용이 가능하고, 이미지만 뿌려주면 되다보니 구형PC든 뭐든 어디서든 바로바로 확인이 가능하기 때문에 프린팅도 금방할거라 판단되었습니다.

Front단에서 만드는 QRCode도 그닥 오랜시간은 걸리지 않겠지만, 혹시라도 구형 태블릿을 활용하시는 분들이 불편할 수 있을 것 같아서 내린 판단입니다.

그리고 Front단을 포기하게 만들게된 결정적인 사항중에 하나입니다만,

ZXing를 사용하면 저에겐 굉장한 이득이 있습니다!

바로 추후 고려중인 Android NativeApp(장비관리)에 소스를 이식 시킬 수 있다는 것이죠. (!!!!!)

이런게 바로 일석이조 아니겠습니까 (잔머리만 잘 굴리네요ㅋㅋㅋㅋ)

 

 

QRCode 생성-Sequence Diagram

QRCode 생성-Sequence Diagram

* 위 이미지에 들어간 글씨체는 네이버 나눔 글씨체인 나눔스퀘어 Bold를 사용했습니다.

* 위 이미지에 들어간 내용은 전부 (픽토그램 등) 직접 제작했음을 명시합니다.

 

우선 Exception에 대해서는 고려하지 않았습니다.

한가지 고려를 해보자면 그럴일은 없어야 하지만, DB저장까지 완료되었는데, QRCode 생성할때 Exception이 일어나면 어쩔것인가? 라는 질문에 대한 답변에는 일단 그런 경우가 생기면 안되겠지만 만일 일어난다면 QRCode는 생성하지 않게 합니다.

데이터의 저장은 완료되었으나, QRCode만 생성은 안되는 것이죠.

그럼 QRCode는 버리는것인지? 아닙니다.

추후 user가 QRCode를 확인하는 페이지에 방문을 하면 만일 QRCode가 생성이 안되어 있는 경우 생성을 하게 만드는 것이죠.

 


오늘은 그간 검토해본 QRCode에 대해서 파악을 해보았습니다.

시간적 여유만 된다면 Front, Back 둘다 구현은 해보고 싶네요 ㅋㅋㅋ

오늘은 불토입니다! 이제 소스나 신나게 구현해야겠습니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

 

버전정보 (v1.0)

 - v1.0 2020.07.18 배포

 

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Project.다원은 개인(karzin)이 기획, 분석, 설계, 디자인, 개발, 유지보수 등

모든 부분을 혼자 맡아 진행하는 개인 프로젝트입니다.

Project.다원 Ensemble

Karzin

abbeea@naver.com

 


[Swift5] 버튼 보이게 / 보이지 않게 하기

(Android와 비교)


iOS 앱 개발을 하다보면 버튼을 보이게 하거나 보이지 않게 해야하는 경우가 있습니다.

이런 경우 코드로는 어떻게 표현을 해야하는지를 알아보겠습니다.

 

우선 안드로이드에서 사용하는 버튼을 보이거나 보이지 않게하는 방법입니다. (setVisibility함수 사용)

 

Android에서 사용하는 방법(Java)

private Button btn_test

//init
btn_test = findViewById(R.id.btn_test);

//버튼을 보이지 않게
btn_test.setVisibility(View.INVISIBLE);

//버튼을 보이게
btn_test.setVisibility(View.VISIBLE);

 

iOS에서는 @IBOutlet으로 Storyboard에서 간단하게 드래그로 변수 선언을 해주시고, layer의 isHidden을 이용해 컨트롤합니다.

 

iOS에서 사용하는 방법입니다.(Swift5)

@IBOutlet weak var btn_test: UIButton!

//버튼 보이지 않게
btn_test.layer.isHidden = true

//버튼 보이게
btn_test.layer.isHidden = false

 

단, 위 코드는 UIBarButtonItem 컴포넌트에서는 먹히지 않습니다. (layer가 선언이 되는 컴포넌트는 전부 가능 - Button, View 등)

 

컴포넌트가 UIBarButtonItem인 경우(Swift5)

@IBOutlet weak var navigation_btn_test: UIBarButtonItem!

//버튼 보이지 않게
navigation_btn_test.isEnabled = false
navigation_btn_test.tintColor = UIColor.clear

//버튼 보이게
navigation_btn_test.isEnabled = true
navigation_btn_test.tintColor = UIColor.black

 

UIBarButtonItem 컴포넌트의 경우 아무래도 isHidden을 사용할 수 없는 모양입니다.

(객체 내에서 Hidden을 시킬 수 있는 함수나 멤버가 없는 모양)

따라서 위의 소스는

1. 버튼을 사용하지 못하게 막음.

2. 색상을 없애버려 없는 버튼처럼 만들어 줌.

두가지를 이용했다고 보시면 됩니다.

 

단, 이는 제가 아직 부족한 부분이 많아서 다른 좋은 방법이 있을 수 있으므로, 좋은 방법이 있다면 업데이트 해두도록 하겠습니다.

(소스의 표현방식은 각양각색이니까요!)

 

 

테스트 장비 : 맥미니(2020)

 

버전정보 (v1.0)

 - v1.0 2020.07.01 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com


[Java] Activity 화면 방향 회전시 제어하기 (Sensor옵션)


 

지난 시간에 Activity 화면의 방향을 제어하는 방법에 대해서 알아보았습니다. (링크)

 

여기서는 sensor옵션 관련(sensor, fullsensor, sensorLandscape, sensorPortrait) 옵션을 주고 회전시에 화면을 제어하는 방법에 대해서 알아보도록 하겠습니다.

 

Manifest에서 화면의 방향을 제어할 옵션을 준 Activity Class에서 onCreate 함수에

displayManager를 선언해 Listner를 등록해주면 됩니다.

아래는 DisplayManager를 선언하고 Listener를 등록해주는 소스

DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
displayManager.registerDisplayListener(displayListener, null);

 

위 소스를 입력하시면 displayListener가 없다고 에러가 날겁니다.

아래는 우리에게 필요한 Listener(displayListener)를 생성합니다.

DisplayManager.DisplayListener displayListener = new DisplayManager.DisplayListener() {
  @Override
  public void onDisplayAdded(int displayId) {
  	//디스플레이가 시스템에서 추가될 때
  }

  @Override
  public void onDisplayRemoved(int displayId) {
  	//디스플레이가 시스템에서 삭제될 때
  }

  @Override
  public void onDisplayChanged(int displayId) {
  	//디스플레이가 변경될때마다
  }
};

위 선언된 Listener에서 내부 Override된 onDisplayChanged 함수를 이용하시면 Activity가 회전될 때마다 캐치하여 원하는 소스를 실행할 수 있습니다.

 

참조

https://developer.android.com/reference/android/hardware/display/DisplayManager.DisplayListener

 

버전정보 (v1.0)

 - v1.0 2020.06.27 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com

 


[자료구조]Java로 Stack 구현해보기 (List 활용)


지난시간에 자료구조 파헤치기를 통해 Stack 구조에 대해서 정리해보았습니다. (페이지로)

 

이번에는 Stack구조를 Java로 만들어 보려합니다. (List 활용)

어렵지 않게 단순히 데이터를 저장할 Stack변수와 Pop 함수 및 Push 함수를 구현해 볼까 합니다.

 

아래는 개발전 설계한 Class-Diagram입니다.

Stack의 Class-Diagram

Class-Diagram 설명

 - stack 변수 : List형식으로 되어있으며, 값을 넣기(push) 위한 공간이라 생각하시면 됩니다.

 - popValues 변수 : 이는 stack변수에서 빠진(pop) 값을 담아두기 위한 공간입니다. (단순히 어떤식으로 빠지나를 확인하기 위한 용도입니다.)

 - push 함수 : String 값을 받아오면 stack 변수에 입력(push) 해줍니다.

 - pop 함수 : stack 변수에서 마지막 값을 꺼냅니다.(pop) 

 - printStack 함수 : push 및 pop 등의 과정을 거쳐 현재 상태를 console창에 print 해줍니다.

 - printPopValue 함수 : pop된 데이터 값을 순서대로 보여줍니다.(popValues 활용)

 

완성 소스 (소스는 github에도 업로드하였습니다. - 링크)

/**
 * Stack 클래스
 * @author karzin
 *
 */
public class Stack {
	
	//Stack 변수 생성 (List)
	private List<String> stack = null;
	
	//Stack 변수에서 pop된 데이터를 저장
	private List<String> popValues = null;
	
	//생성자 - stack을 초기화해줌
	Stack() {
		stack = new ArrayList<String>();
		popValues = new ArrayList<String>();
	}
	
	//stack에 값을 넣음(push)
	public void push(String pushValue) {
		stack.add(pushValue);
	}
	
	//stack에서 값을 뺌(pop)
	public String pop() {
		String popValue = "Stack이 비어있습니다.";
		
		if(stack.size() > 0) {
			popValue = stack.remove(stack.size()-1);
			popValues.add(popValue);
		} else {
			System.err.println(popValue);
		}
		
		return popValue;
	}
	
	//stack 내부에 있는 값을 모두 출력한다.
	public void printStack() {
		int i = 0;
		
		for(String value : stack) {
			if(i < value.length()) {
				i = "| ".length() + value.length() + " |".length();
			}
		}
		
		for(int s = stack.size()-1; s >= 0; s--) {
			int length = "| ".length() + stack.get(s).length() + " |".length();
			length = i-length;
			System.err.print("| "+stack.get(s));
			for(int j = 0; j < length; j++) {
				System.err.print(" ");
			}
			System.err.print(" |");
			System.err.println();
			for(int j = 0; j < i; j++) {
				System.err.print("-");
			}
			System.err.println();
		}
		
		System.err.println();
	}
	
	//popValues 변수에 있는 값을 순서대로 보여줌.
	public void printPopValue() {
		System.out.print("popValues ==> ");
		System.out.println(popValues);
		
		System.out.println();
	}

}

 

테스트해보기 (Main Class 생성 및 실행 -> 소스는 github에도 업로드하였습니다. - 링크)

stack.push("A");
stack.printStack();

stack.push("B");
stack.printStack();

stack.pop();
stack.printPopValue();

stack.push("C");
stack.printStack();

stack.pop();
stack.printPopValue();

stack.pop();
stack.printPopValue();

 

결과

-> Debug 모드로 실행하셔서 한줄 한줄 어떤식으로 바뀌는지 확인해보시면 더욱 이해하기 쉽습니다.

---

졸면서 하느라고 함수도 소스도 많이 적은느낌이네요.

버그같은거 있다면 댓글남겨주시면 최대한 바로 수정하겠습니다.

감사합니다.

 

 

** 그림에 사용된 글자체는 네이버 나눔글꼴의 나눔스퀘어 Bold입니다.

 

버전정보 (v1.1)

 - v1.0 2020.06.18 배포

 - v1.1 2020.06.23 제목 말머리 [자료구조] 추가

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

 

Karzin

abbeea@naver.com





[Java]안드로이드 권한요청 class


 

어플을 개발하다보면 권한요청을 해야하는 경우가 많이 생깁니다.

특히 센서나, 저장소의 권한을 요청하는 경우가 많은데 이를 조금 더 편하게 사용할 수 있도록 Class로 만들었습니다.

사용방법은 심플합니다.

프로젝트에 .class 파일 넣어주고! 객체 생성해서! 함수한번 실행해주면 끝나게 만들어놨습니다!

(혼자 쓰다가 같이 쓰면 좋을것 같아서..)

 

Github 권한요청 Class : https://github.com/dawon-karzin/Android_PermissionCheck_Java

 

dawon-karzin/Android_PermissionCheck_Java

안드로이드 권한 요청 클래스입니다.(java). Contribute to dawon-karzin/Android_PermissionCheck_Java development by creating an account on GitHub.

github.com

 -> 버그등은 이슈로 남겨주시면 빠른시일내에 수정토록하겠습니다.

 

 - 구조

  • 클래스명 : PermissionCheck
  • 생성자 파라미터 : Activity
  • 내부 함수 :
    •   check(List<String>)
    •   permissionGranted()
  • 실행 방식 :
    • PermissionCheck 객체 생성(생성시 현 Activity를 매개변수로 전달)
    • 권한 요청을 받아야하는 List를 전달하여 check함수 실행
    • check함수 내에서 매개변수로 전달받은 List를 확인하여 권한이 부여되지 않은(Denied) 권한을 List로 생성
    • 이후 permissionGranted 함수를 실행하여 권한이 부여되지 않은(Denied) 권한에 대하여 요청(request)을 함
  • 사용 방법 :
    •   permission처리를 할 activity 상속 클래스에서 PermissionCheck 클래스 선언.
    •   check함수(파라미터로 permission 리스트를 전달) 사용함으로써 유저에게 권한요청 실행
//권한요청을 받을 List 생성
List myPermission = Arrays.asList( new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE});

//권한요청 class 생성 (생성시 지금의 Activity를 매개변수로 전달)
PermissionCheck permissionCheck = new PermissionCheck(this); 

//권한요청 시작(권한요청을 받아야하는 List를 매개변수로 전달)
permissionCheck.check(myPermission);

 

-> 개인적으로 개발할때 class 옮겨가며 사용하는 중인데, 생각해보니 permissionDeniedList 변수를 왜 전역으로 선언 했는지 기억이 안나네요;; 무언가 이유가 있었던 것 같은데....... 졸면서 해서그런가;;; (나중에 생각나면 업데이트 해놓겠습니다.)

 

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른시일내에 조치하도록 하겠습니다.

 

Karzin

abbeea@naver.com

 


[Kotlin, JAVA]

밀리세컨드 단위 시간 구하기


간혹 파일명을 만든다던가하는 특수한 경우마다 중복이 일어나지 않기 위해 밀리세컨드 단위의 시간을 구해야하는 경우가 있습니다.

(키값이 중복되지 않는다는 점에선 가장 편한 방법일지도 모르겠지요. 주요 예로는 파일의 저장(영상, 사진) 등)

 

 - Kotlin 현재 시간 구하기

System.currentTimeMillis()

val testTime = "${System.currentTimeMillis()}"

 

 - JAVA 현재 시간 구하기

System.currentTimeMillis();

String testTime = String.valueOf(System.currentTimeMillis());

 

return type는 long형입니다.

 

 *** Reference : https://developer.android.com/reference/java/lang/System#currentTimeMillis()

 

System  |  Android 개발자  |  Android Developers

System public final class System extends Object java.lang.Object    ↳ java.lang.System The System class contains several useful class fields and methods. It cannot be instantiated. Among the facilities provided by the System class are standard input, stand

developer.android.com

 *** 소스에 문제가 있을 시 댓글달아주시면 최신화하도록 하겠습니다. 감사합니다

 

+ Recent posts