Oracle Textのcontains文を使用してJPA Criteria Queryを実行することはできますか?JPAでのOracle Text Criteria Query
答えて
APIはすべてのRDBMSに存在し、 "LIKE"/"SUBSTRING"のような構造を提供しています。これは、TEXT列に対してOracle上で使用されたときにその形式にマップできますが、再び標準 SQLを使用します。
openjpa用のOracleTextDictionaryを作成しました。引数に「マジカル」マーカーを前置すると、通常の「like」演算子が「contains」演算子に変換されました。
このようにして、QueryDSLまたはCriteria Language(またはJPQL)をOracleテキストとともに使用することができます。
ディクショナリは、引数にマジックマーカーを含むLIKE文を検出し、SQLを書き換えてCTX CONTAINSコールを使用します。
1つの欠点は、簡単な方法でスコアにアクセスできないことですが、スコアで注文するようにドライバを強化することが可能です。
特定のデータベースへのデータベースクエリをチューニングするための同様のメカニズムがあると仮定して、私はそれを休止状態にすることは可能です。
package se.grynna.dict;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.sql.OracleDictionary;
import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.Select;
public class OracleTextDictionary extends OracleDictionary {
public static final String CTX_MAGIC_MARKER = "@[email protected]";
final static Pattern likePattern = Pattern
.compile("t(\\d+)\\.(\\S+) LIKE (\\?)");
@Override
protected SQLBuffer toSelect(SQLBuffer select,
JDBCFetchConfiguration fetch, SQLBuffer tables, SQLBuffer where,
SQLBuffer group, SQLBuffer having, SQLBuffer order,
boolean distinct, boolean forUpdate, long start, long end,Select sel) {
SQLBuffer sqlBuffer = super.toSelect(select, fetch, tables, where,
group, having, order, distinct, forUpdate, start, end, sel);
SQLBuffer tmpBuf = sqlBuffer;
String sql = tmpBuf.getSQL();
int label = 1;
for (Matcher m = likePattern.matcher(sql); m.find(); sql = tmpBuf.getSQL()) {
int argPos = m.start(3);
int argIdx = findArgIdx(sql, argPos);
Object o = tmpBuf.getParameters().get(argIdx);
if(o == null) break;
String arg = o.toString();
if (arg.startsWith(CTX_MAGIC_MARKER)) {
if (tmpBuf == sqlBuffer) {
tmpBuf = new SQLBuffer(sqlBuffer);
}
arg = arg.substring(CTX_MAGIC_MARKER.length());
setParameter(tmpBuf, argIdx, arg);
String aliasNo = m.group(1);
String colName = m.group(2);
}
String replace = String.format("(CONTAINS(t%s.%s,?,%d)>0)",
aliasNo, colName, label++);
tmpBuf.replaceSqlString(m.start(), m.end(), replace);
m.reset(tmpBuf.getSQL());
}
}
return tmpBuf;
}
@SuppressWarnings("unchecked")
private void setParameter(SQLBuffer tmpBuf, int argIdx, String arg) {
tmpBuf.getParameters().set(argIdx, arg);
}
private int findArgIdx(String sql, int argPos) {
int count = -1;
for (int i = 0; i <= argPos; i++) {
char c = sql.charAt(i);
if (c == '?') {
count++;
}
}
return count;
}
}
例:次の(明らかに不自然)入力が生成がパラメータで呼び出される:サイドノートとして
:1 "@[email protected] near ponies"
:2 "@[email protected]"
:3 "@[email protected]%"
:4 "abc1%" <-- an ordinary like :-)
:5 "@[email protected]%"
JPQL
select distinct customer
from Customer customer
where customer.custName like :a1 and customer.custName like :a2 and customer.custName like :a1 and customer.custId in (select d.custId
from Customer d
where d.custName like :a3 or d.custName like :a1)
SQL
SELECT t0.custId,
t0.custName
FROM Customer t0
WHERE ((CONTAINS(t0.custName,?,1)>1)
AND (CONTAINS(t0.custName,?,2) >1)
AND (CONTAINS(t0.custName,?,3) >1)
AND t0.custId IN
(SELECT t1.custId
FROM Customer t1
WHERE (t1.custName LIKE ? <---- the like survives....
OR (CONTAINS(t1.custName,?,1)>1))
))
AND ROWNUM <= ?
:QueryDslは実際にjpaとsqlのバックエンドが 'like'ステートメントを生成する、Luceneバックエンドのための'contains '演算子があります。
私はcontains演算子をオーバーロードする方法を理解していないので、それを使うことができます。 (WebSphereにバンドルされているバージョンを使用しているので、コードを書き直す以外にはできません。)
したがって、私はQuertyDSLを使用するときれいに見えるように小さな静的メソッドに頼っています。
// x.where(c.custName.like(CTX.contains("omg near ponies"))));
JPQLは、いくつかの抽象化(またはプラグイン)を提供することができれば、それは、フルテキスト検索エンジンのためにも、よりよいだろう...
基準は、データベース機能がによって呼び出されることを可能にする機能()APIをサポートしています名。
qb.gt(qb.function("CONTAINS", root.get("name"), qb.parameter("name"), qb.literal(1)), 1)
また、EclipseLinkでは、FUNCキーワードを使用してJPQLでこれをサポートしています。
- 1. JPA Criteria query Path.get left join is possible
- 2. JPA Criteria Query Builder:最後のエントリを取得する
- 3. タプル式のJPA Criteria in句
- 4. Criteria API JPA
- 5. JPA criteria API order by NULL last
- 6. Criteria JPA 2 with 3 tables
- 7. JPA Criteria API group_concat usage
- 8. JPA/Criteria Likeパーセント文字
- 9. NHibernate Criteria Query - Distinctを選択
- 10. JPA Criteria API IN式パラメータリスト
- 11. JPA Criteria builder IN句クエリ
- 12. JPA/Hibernate Join Query
- 13. Spring JPA @query image
- 14. ORACLE INSERT QUERY内のSELECT QUERY
- 15. HibernateのJPAスタイルのCriteria/CriteriaBuilderクエリ
- 16. JPA Criteria Builderの/ Case文の場合
- 17. gtkSourceView - query-tooltip-textの使用
- 18. JPA複数のパラメータを持つCriteria API
- 19. JPA 2 + Criteria API - サブクエリの定義
- 20. camel-jpa query - パラメータで選択
- 21. jpa hibernate mysql query broken
- 22. jpa named query not found
- 23. spring jpa onetomany relationship @Query not working
- 24. oracle outer join query
- 25. ORACLE Query Count Slow
- 26. Oracle sql-hierarchical query
- 27. Oracle SQL Query 2
- 28. Oracle 11g Sys Query
- 29. Oracle Query History
- 30. Oracle Query on Regexp_substr
だから、私はJPAネイティブクエリーに文字列連結とforgoタイプの安全性を使用しなければならないと思います。ああ。 – Ryan