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. NHibernate Criteria Query - Distinctを選択
- 3. Criteria JPA 2 with 3 tables
- 4. JPA Criteria API group_concat usage
- 5. JPA/Hibernate Join Query
- 6. JPA Criteria API IN式パラメータリスト
- 7. jpa named query not found
- 8. oracle outer join query
- 9. Oracle 11g Sys Query
- 10. HibernateのJPAスタイルのCriteria/CriteriaBuilderクエリ
- 11. JPA Criteria Builderの/ Case文の場合
- 12. JPA 2 + Criteria API - サブクエリの定義
- 13. JPA複数のパラメータを持つCriteria API
- 14. sql oracle query data export
- 15. HibernateでCriteria Queryを作成するには?
- 16. Sybase TEXTとOracle CLOBのパフォーマンス
- 17. サブクラスを使用した抽象コレクションのJPA criteria検索プロパティ
- 18. 春データJPA @query注釈、真nativeQuery =、
- 19. JPA CriteriaクエリAPIと2列で注文する
- 20. JPA Criteria APIで変数とParameterExpressionを使用する場合
- 21. Spring JPA:クエリービルダーとCriteria Builderのどちらを使用するのですか?
- 22. Oracle Query TermDates固有の結果
- 23. Oracle Query Optimizerの診断出力
- 24. Oracle Locator/Spatial QueryのPro COBOLサポート
- 25. JPA&Criteria API - 特定の列のみを選択する
- 26. Oracle updateXML - text()とは何ですか?
- 27. JPA/Hibernate Criteriaを使用して日付を取得する
- 28. DATE列のINSERT QUERYが必要です。Oracle 11Gの値
- 29. OracleのDATEおよび休止状態/ JPAマッピングOracle表の
- 30. Oracleユーザー定義型へのJPAマッピング
だから、私はJPAネイティブクエリーに文字列連結とforgoタイプの安全性を使用しなければならないと思います。ああ。 – Ryan