728x90

 

현상: MyBatis에서 아래처럼 SQL시 테이블 별명을 사용하려고 했다. 

SELECT 
  M.CLUB_NO,
  C.CLUB_NM,
  M.I_DATE,
  M.I_USER,
  M.U_DATE,
  M.U_USER,
  M.USE_YN,
  M.USER_AUTH,
  M.USER_NO
  
  FROM 테이블1 M, 테이블2 C
   		WHERE 
   			M.USER_NO = 유저번호
   			AND M.USE_YN = 'Y'
        AND C.USE_YN = 'Y'
        AND M.CLUB_NO = C.CLUB_NO;
        

 

Oracle DB로 개발 중이므로, Sqldeveloper에서 쿼리 실행시에는 문제가 없었는데,

MyBatis로 동작시키니 BadSqlGrammarException:~~~ 이 뜨면서 에러가 발생했다.

 

해결: 다른 프로젝트에서 <!cdata[  ~~~~~ ]>를 사용하는건 문제가 없길래 그대로 적용해보니 해결되었다.

 

 

Q. 그렇다면 <!cdata는 왜 쓰는걸까?

 

출처: https://javacpro.tistory.com/5 [버물리의 IT공부]

 

Mybatis 사용시 쿼리문에 문자열 비교연산자나 부등호를 처리할 때가있습니다.

그러면 < 와 같은 기호를 괄호인지 아니면 비교연산자 인지 확인이 되지않아요.

이외에도 특수문자 사용하는데 제한이있습니다.

 

<select id ="list" parameterType="int" resultType="board.test.testDto>

select *

from employees

where salary > 100

</select>

 

 

대략 이런식으로요 

 

이럴때 사용한것이 <![CDATA[  입니다.

CDATA 안에 들어가는 문장을 문자열로 인식하게 합니다.

 

 

<select id = "list" parameterType="int" resultType="board.test.testDto>

<![CDATA[

select *

from employees

where salary > 100

]]>

</select> 

 

이렇게 사용하면 SQL안에 특수문자가 들어가도 문자열로 인식하기때문에

문제를 해결할수있습니다. 



출처: https://javacpro.tistory.com/5 [버물리의 IT공부

 

 

 

<![CDATA[ 로 해결되었다는건, 그냥 <select>문 안에 쓰게 되면, mapper가 테이블 별명을 제대로 해석을 못하는건가 싶다.

728x90
728x90

<내가 사용한 방법>

- Oracle DB 기준, Sequnce 사용 방법

 + insert문에 sysdate 추가

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="com.test.dao.PersonInterface">
    
     <insert id="insertUserInfo" parameterType="HashMap">
	    <selectKey keyProperty="user_no_seq" resultType="integer" order="BEFORE">
	   		 select USER_NO_SEQ.nextval FROM DUAL
  		</selectKey>
	     
    	INSERT INTO PERSON 
    		(USER_NO, C_EMAIL, C_NAME, JOIN_DATE, OS_TYPE)
    		VALUES(
    			   #{user_no_seq},
    			   #{C_EMAIL},
    			    #{C_NAME},
    			   sysdate,
    			   #{OS_TYPE}
    			   )
    </insert>
   
</mapper>

 

 

 

+ 참고

출처: https://taetaetae.github.io/2017/04/04/mybatis-useGeneratedKeys/

 

# selectKey 옵션

Oracle 같은 경우는 Auto Increment 가 없고 Sequence를 사용해야만 하기 때문에 위 옵션을 사용할수가 없다. 하지만 다른 우회적인(?) 방법으로 위와같은 효과를 볼수가 있다.

파라미터의 모델이나 java구문은 위와 동일하고 xml 쿼리 부분만 아래와 같이 설정해주면 된다.

<insert id="insertStudents" parameterType="Student">

<selectKey keyProperty="id" resultType="int" order="BEFORE">

select SEQ_ID.nexyval FROM DUAL

</selectKey>

insert into Students

(id, name , email)

values

(#{id}, #{name}, #{email})

</insert>

위와같은 코드에서 쿼리가 실행되기 전에 id값에 Sequence에 의해 값을 셋팅하게 되고, 자동적으로 해당 값을 Student의 id에 set하게 되서 동일한 결과를 볼수가 있다.

 

 

---------------------------------------------------------------------------------------------------

하단은 추가 참고 사항

 

DBMS 별 selectKey 방법

 

출처 : http://kamsi76.egloos.com/377946

 

MySql

<insert id="insertContent" parameterClass="content">
    <![CDATA[
    INSERT INTO CONTENT (
        CREATED_DATE, TITLE, CONTENT, CONTENT_TYPE
    ) VALUES (
        now(), #{title}, #{content}, #{contentType}
    )
    ]]>
    <selectKey keyProperty="seqId" resultClass="int">
        SELECT LAST_INSERT_ID()
    </selectKey>
</insert>



MSSQL

<insert id="createProjectBasicInfo" parameterClass="prjIdx">
    <selectKey keyProperty="prj_info_seq" resultClass="int">

        INSERT INTO PRJ_INFO (
            ...
        ) VALUES (
             ...
        ) 
        SELECT SCOPE_IDENTITY()

    </selectKey>
</insert>


Oracle

<insert id="insert_message" parameterClass="java.util.HashMap">
    <selectKey keyProperty="message_id" resultClass="Integer">
        SELECT message_id_seq.nextval FROM DUAL
    </selectKey>
    INSERT INTO guestbook_message (message_id, guest_name, password, message)
    VALUES(#{message_id}, #{gName}, #{pw}, #{ms})
 </insert>

[출처] MyBatis 에서 selectkey 사용 방법|작성자 moonv11

 

 

 

Reference

https://blog.naver.com/moonv11/60181183377

728x90
728x90

* RxJava 권장하는 학습순서

  1. Observable 클래스 명확하게 이해 (특히 뜨거운(Hot) Observable과 차가운(Cold) Observable의 개념을 꼭 이해해야 함)

  2. 간단한 예제로 map(), filter(), reduce, flatMap() 함수의 사용법을 익힙니다.

  3. 생성 연산자, 결합 연산자, 변환 연산자 등 카테고리별 주요 함수를 공부

  4. 스케줄러의 의미를 배우고 subscribeOn()과 observeOn() 함수의 차이를 알아둡니다.

​5. 그 밖의 디버깅, 흐름 제어 함수를 익힙니다.

 

2장(Observable) => 3장(map-filter-reduce) => 4장(주요 연산자) => 5장(RxJava 때문에 달라지는 비동기 프로그래밍, 스케줄러) => 6장(RxAndroid) => 7장(디버깅, 예외처리)

  • 자바 8을 사용하지 않아도 됨. 자바 8에서 제공하는 Consumer, Predicate, Function과 같은 함수형 인터페이스를 자체 구현했으므로 자바 6 이상이면 동작.

    • But, 8의 람다 표현식과 함수 레퍼런스를 활용하는 코드는 가독성을 좋게함. (람다식 & 함수 레퍼런스 공부)

------------------------------------------------------------------------------------------------

 

1. RxJava의 각 개념

 

(1) Observable

Observable.just(text)

- 관찰 가능한, 즉 데이터를 방출하는 스트림

- Observable.just(text)라고 하면, Observable이 text라는 데이터 하나를 just 방출했다고 이해

 

 

(2) Observer

.subscribe(fetchObserver());

- Observable에서 흘러나온 데이터를, Observer가 subscribe(구독)해서 반응

 

==> 이 때 이에 대한 연결(구독) 자체를 (3) Subscription이라고 하는 것

 

(4) Scheduler

- multi-thread를 적용하고자 할 때 사용.

.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

- SubscribeOn은 main-thread가 아닌, worker-thread를 지정하는 것

- ObserveOn은 데이터를 가공해서 써먹을 때, 어디에 결과를 보낼 것이냐는 것

 

 

 

+

 

1. Hot Observable vs. Cold Observable

- Hot Observable: Observable을 생성하자마자 아이템들을 흘려보냄. 마우스 이벤트 , 키보드 이벤트 , 시스템 이벤트등이 주로 사용된다.

- Cold Observable: 생성하자마자가 아니라, 실행을 미루고 있다가 Subscribe할때 아이템들을 흘려보냄. 누가 구독해주지 않으면 데이터를 배출을 하지 않음. 일반적인 웹 요청, 데이터베이스 쿼리등이 사용되며 내가 요청하면 결과를 받는 과정을 거친다.

 

일반적인 방법이 Hot Observable이고,

Cold Observable은 fromCallable등의 Operator로 구현해야함.

 

 

2. fromCallable

- Callable은 Generic으로 받은, 오브젝트 타입으로 value를 return 해주는, Thread에 전달할 작업

- Callable과 Runnable의 공통/차이

공통: 비슷하게, 다른 쓰레드에 의해서 실행되어질 수 있는 클래스 객체를 위한 인터페이스.

차이: 그러나 Callable은 (Runnable처럼 바로 Thread에 인자로 전달할 수 없고) ThreadPool을 사용해서 전달함.

       또한 Runnable은 return값이 없고 Exception을 낼 수 없으나, Callable은 return이 존재하고, Exception을 낼 수 있음.

 

 

 

1. Observable 세부 사항

RxJava의 Observable은 세가지의 알림을 구독자에게 전달

  • onNext : Observable이 데이터의 발행을 알린다. 기존의 옵서버 패턴과 같음.

  • onComplete : 모든 데이터의 발행을 완료했음을 알린다. onComplete이벤트는 단 한번만 발생하며, 발생한 후에는 더 이상 onNext 이벤트가 발생해선 안 된다.
  • onError : 에러 발생을 알림. onError 이벤트가 발생하면 이후에 onNext 및 onComplete 이벤트가 발생하지 않는다. 즉, Observable의 실행을 종료.

 

2. Disposable 객체

  • void dispose() / boolean isDisposed() => 2개 함수만 존재

  • dispose()

    • Observable에게 더 이상 데이터를 발행하지 않도록 구독을 해지하는 함수

    • Observable이 onComplete 알림을 보냈을 때, 자동으로 dispose()를 호출해

      Observable과 구독자의 관계를 끊는다. => 따로 dispose() 호출 X

  • isDisposed()

    • Observable이 데이터를 발행하지 않는지 (구독을 해지했는지) 확인하는 함수

    • 구독을 해지했으면 -> true

https://www.youtube.com/watch?v=_MI5X0jrfIo

 

 

 

 

 

 

 

 

Reference

https://dev-daddy.tistory.com/26

https://taeiim.tistory.com/entry/RxJava2-1-%EB%A6%AC%EC%95%A1%ED%8B%B0%EB%B8%8C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EA%B3%BC-RxJava

https://developer88.tistory.com/86

https://developer88.tistory.com/87

https://javaexpert.tistory.com/794

https://taeiim.tistory.com/entry/RxJava2-2-Observable-Single-Maybe-%EB%9C%A8%EA%B1%B0%EC%9A%B4%EC%B0%A8%EA%B0%80%EC%9A%B4-Observable-%ED%8C%A9%ED%86%A0%EB%A6%AC%ED%95%A8%EC%88%98?category=759183

 

728x90

'Dev > Java' 카테고리의 다른 글

[Java] Java SE, EE, ME, FX의 차이  (0) 2019.10.16
[Java] Calendar 객체 사용시 'set' not working  (0) 2019.09.19
[Java] Singleton Pattern 사용시  (0) 2018.10.02
728x90


에러: javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'.

해결방법:에러 발생시 하단의 라이브러를 추가 필요

 

pom.xml 파일 수정

<dependency>
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <version>3.0.0</version>
</dependency>

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.el</artifactId>
    <version>3.0.0</version>
</dependency>

 

spring boot build.gradle 파일 수정

    compile('javax.el:javax.el-api:3.0.0')

    compile('org.glassfish:javax.el:3.0.0')

 

 

 

Reference

https://knight76.tistory.com/entry/javaxvalidationValidationException-HV000183-Unable-to-initialize-javaxelExpressionFactory-해결하기

 

728x90

+ Recent posts