그냥 뭔가 조금 이상했는데 이유는 잘 모르겠다 ..

 

 

querydsl 4.1.4버전을 사용중이였는데 쿼리가 나가는 부분에 UnsupportedOperationException 에러가 발생했다.

 

추적을 좀 해보고싶었는데 구글링해도 도움이 될만한 내용은 찾지 못했다

 

 

일단 querydsl 버전을 4.1.4 -> 4.4.0(20201026 최신버전)  으로 바꾸니까 정상 동작했다.

 

간단하게 디버깅해봤을때

 

com.querydsl.jpa.JPQLSerializer 내부에 아래와 같은 함수가 있는데

    public void visitConstant(Object constant) {
        boolean wrap;
        if (this.inCaseOperation && this.templates.isCaseWithLiterals()) {
            if (constant instanceof Collection) {
                this.append("(");
                wrap = true;

                for(Iterator var5 = ((Collection)constant).iterator(); var5.hasNext(); wrap = false) {
                    Object o = var5.next();
                    if (!wrap) {
                        this.append(", ");
                    }

                    this.visitLiteral(o);
                }

                this.append(")");
            } else {
                this.visitLiteral(constant);
            }
        } else {
            wrap = this.templates.wrapConstant(constant);
            if (wrap) {
                this.append("(");
            }

            this.append("?");
            if (!this.getConstantToLabel().containsKey(constant)) {
                String constLabel = String.valueOf(this.getConstantToLabel().size() + 1);
                this.getConstantToLabel().put(constant, constLabel); // <-- 요기
                this.append(constLabel);
            } else {
                this.append((String)this.getConstantToLabel().get(constant));
            }

            if (wrap) {
                this.append(")");
            }
        }

    }

아래부분에 this.getConstantToLabel().put(constant, constLabel); 로 put을 사용하는데 여기서 사용하는 getConstantToLabel()이 리턴하는 자료구조가 UnmodifiableMap이다.

 

참고로 UnmodifiableMap은 put을 구현하지 않았기 때문에 호출시 UnsupportedOperationException 을리턴하는게당연하다.

 

 

버전을 4.4.0으로 올려서 확인해보면 같은 부분이라도 조금 다른걸 확인할 수 있다.

            this.append("?");
            if (!this.getConstantToAllLabels().containsKey(constant)) {
                Integer constLabel = this.getConstantToNumberedLabel().size() + 1;
                this.getConstantToNumberedLabel().put(constant, constLabel);
                this.append(constLabel.toString());
            } else {
                this.append((String)this.getConstantToAllLabels().get(constant));
            }

getConstantToLabel() -> getConstantToNumberedLabel() 으로 변경된 것을 확인할 수 있는데 실제로 getConstantToNumberedLabel() 가 리턴하는 자료구조는 HashMap이다. 고로 정상동작한다.

 

 

내가 api를 제대로 안본것도 있겠지만 왜 4.1.4 에서는 UnmodifiableMap을 리턴하게 해놨을지 ...

 

 

 

 

 

-결론

버전 올리면 된다.

+ Recent posts