QuerySpec은 객체를 생성 후 사용한다.
QuerySpec qs = new QuerySpec();
밑에는 자주 쓰이는 것 위주로 정리하였다.
다음의 쿼리를 쿼리스펙으로 만든다면??
SELECT * FROM WTDocument;
QuerySpec qs = new QuerySpec(WTDocument.class);
addClassList()
도 쓸 수 있지만 appendClassList()
를 쓰는 것이 좋다.
QuerySpec qs = new QuerySpec();qs.appendClassList(WTDocument.class, true);
위와 같이 두 가지로 만들 수 있지만 쿼리 결과를 활용할 때 차이점이 있다.
QueryResult qr = PersistenceHelper.manager.find(qs);while(qr.hasMoreElements()){WTDocument doc = (WTDocument) qr.nextElement();}
QueryResult qr = PersistenceHelper.manager.find(qs);while(qr.hasMoreElements()){Object[] obj = (Object[]) qr.nextElement();WTDocument doc = (WTDocument) obj[0];}
QuerySpec은 toString()
으로 실제 쿼리문을 볼 수 있다.
out.print(qs.toString());
위 QuerySpec의 toString()
은 다음과 같다.
결과를 보면 appendClassList
했던 순서에 따라 A0로 alias가 매겨지는 것을 확인할 수 있다.
SELECT A0.* FROM WTDocument A0;
alias를 활용해 좀 더 복잡한 쿼리를 만들어보자. (아래 B0.idA3D2iterationInfo
는 WTDocument 테이블의 creator id 이다.)
아래 쿼리를 가지고 QuerySpec을 만들면..
SELECT * FROM WTDocument B0, WTUser B1WHERE B0.idA3D2iterationInfo = B1.ida2a2;
아래와 같이 만들 수 있다.
아래와 같이 qs.getFromClause().setAliasPrefix()
를 써서 alias를 직접 지정할 수도 있다.
참고로 new int[]{doc_idx, user_idx}
는 new int[]{0, 1}
로 바꿀 수도 있다.
QuerySpec qs = new QuerySpec();qs.getFromClause().setAliasPrefix("B");int doc_idx = qs.appendClassList(WTDocument.class, true);int user_idx = qs.appendClassList(WTUser.class, true);qs.appendWhere(new SearchCondition(WTDocument.class, WTDocument.CREATOR + ".key.id",WTUser.class, WTUser.PERSIST_INFO + ".theObjectIdentifier.id"),new int[]{doc_idx, user_idx});
방금 전 예시에서 봤던 형태이다. 쿼리로는 A0.idA3D2iterationInfo = A1.ida2a2
와 같이 나타낼 수 있겠다. inner-join을 할 때 자주 쓰인다.
하나의 테이블의 컬럼을 비교할 때 쓰인다.
QuerySpec qs = new QuerySpec();int doc_idx = qs.appendClassList(WTDocument.class, true);qs.appendWhere(new SearchCondition(WTDocument.class, WTDocument.CREATOR + ".key.id",SearchCondition.EQUAL, new Long(11)),new int[]{0});
위 QuerySpec은 아래와 같은 쿼리로 나타낼 수 있다.
SearchCondition은 A0.idA3D2iterationInfo = 11
부분을 만들 때 쓰인 것을 알 수 있다.
SELECT A0.* FROM WTDocument A0WHERE A0.idA3D2iterationInfo = 11
ClassAttribute 끼리 연산자로 비교하는 형태인데 Outer-Join과 같이 '=' 가 아닌 연산자를 사용할 때 쓰인다.
QuerySpec qs = new QuerySpec();int doc_idx = qs.appendClassList(WTDocument.class, true);int user_idx = qs.appendClassList(WTUser.class, true);qs.appendWhere(new SearchCondition(new ClassAttribute(WTDocument.class, WTDocument.CREATOR + ".key.id"),SearchCondition.NOT_EQUAL,new ClassAttribute(WTUser.class, WTUser.PERSIST_INFO + ".theObjectIdentifier.id")),new int[]{doc_idx, user_idx});
위 QuerySpec은 아래와 같은 쿼리로 나타낼 수 있다.
SearchCondition은 A0.idA3D2iterationInfo <> A1.idA2A2
부분을 만들 때 쓰인 것을 알 수 있다.
SELECT A0.*,A1.* FROM WTDocument A0, WTUser A1WHERE A0.idA3D2iterationInfo <> A1.idA2A2
이전에 봤던 ClassAttribute 대신 SubSelectExpression를 쓴 형태인데 서브쿼리를 사용하고 싶을 때 사용한다.
QuerySpec subQs = new QuerySpec();int user_idx = subQs.appendClassList(WTUser.class, false);subQs.appendSelect(new ClassAttribute(WTUser.class, WTUser.PERSIST_INFO + ".theObjectIdentifier.id"), true);QuerySpec qs = new QuerySpec();int doc_idx = qs.appendClassList(WTDocument.class, true);qs.appendWhere(new SearchCondition(new ClassAttribute(WTDocument.class, WTDocument.CREATOR + ".key.id"),SearchCondition.IN, new SubSelectExpression(subQs)),new int[]{0});
위 QuerySpec은 아래와 같은 쿼리로 나타낼 수 있다.
SearchCondition은 A0.idA3D2iterationInfo IN (SELECT A0.idA2A2 FROM WTUser A0)
부분을 만들 때 쓰인 것을 알 수 있고 SubSelectExpression
는 서브쿼리를 만들 때 쓰였다는 것을 알 수 있다.
SELECT A0.* FROM WTDocument A0WHERE A0.idA3D2iterationInfo IN (SELECT A0.idA2A2 FROM WTUser A0)
SearchCondition(Persistable-class, columName, Persistable-class, columName) 형태가 사용된다.
LEFT_OUTER_JOIN과 RIGHT_OUTER_JOIN이 있다.
SearchCondition(ClassAttribute, SearchCondition.LEFT_OUTER_JOIN, ClassAttribute) 형태가 사용된다.
SearchCondition(ClassAttribute, SearchCondition.RIGHT_OUTER_JOIN, ClassAttribute) 형태가 사용된다.
SQL 기본 내장함수 MAX, COUNT, UPPER, DECODE 등을 사용할 때 쓰인다.
QuerySpec qs = new QuerySpec();int idxA = qs.appendClassList(WTDocument.class, false);ClassAttribute name = new ClassAttribute(WTDocument.class, WTDocument.TITLE, "A0");SQLFunction max = SQLFunction.newSQLFunction("UPPER", name);qs.appendSelect(max, false);
위 QuerySpec은 아래와 같은 쿼리로 나타낼 수 있다. UPPER 함수가 사용되었다.
SELECT UPPER(A0.title) FROM WTDocument A0
SQL에서 Order By와 같은 정렬을 사용하고 싶을 때 쓰인다.
QuerySpec qs = new QuerySpec();int idxA = qs.appendClassList(WTDocument.class, true);qs.appendOrderBy(new OrderBy(new ClassAttribute(WTDocument.class, WTDocument.TITLE), false), new int[] { idxA });
위 QuerySpec은 아래와 같은 쿼리로 나타낼 수 있다.
SELECT A0.* FROM WTDocument A0 ORDER BY A0.title
링크테이블의 role 중 하나로 다른 role를 가져오고 싶을 때 쓰인다.
전에 알아본 방법과 같이 조인을 활용해 조회할 수 있지만 더 간략한 코드로 데이터를 가져올 수 있다. 꽤 navigate()
가 쓰이기 때문에 코드를 읽을 줄 알려면 무엇인지 알아야 한다.
아래와 같이 QueryResult로 받을 때 WTUser로 바로 받을 수 있다.
WTPartMaster master = (WTPartMaster) CommonUtil.getObject("wt.part.WTPartMaster:1182143");QueryResult qr = PersistenceHelper.manager.navigate(master, "roleA", MasterACLWTUserLink.class);while(qr.hasMoreElements()){WTUser doc = (WTUser) qr.nextElement();}
위 QuerySpec의 navigate()
는 아래와 같은 쿼리로 나타낼 수 있다.
SELECT A1.* FROM MasterACLWTUserLink A0, WTUser A1WHERE A0.ida3a5 = A1.ida2a2AND A0.ida3b5 = '1182143'