是否有可能使用Oracle Text的contains语句执行JPA Criteria Query,如果是这样的话?JPA中的Oracle Text Criteria查询
6
A
回答
2
怀疑它。 API遍布所有的RDBMS,并且提供了某些结构,如“LIKE”/“SUBSTRING”,当在Oracle上用于TEXT列时,可以映射为某种形式的结构,但它们可能只是使用标准 SQL。没有符合标准的方法来坚持这一点
2
我刚刚为openjpa编写了一个OracleTextDictionary,它将普通的'like'运算符转换为'contains'运算符,当参数带有一个“魔法”标记前缀时。
通过这种方式,可以在Oracle文本中使用QueryDSL或Criteria Language(或JPQL)。
字典使用参数中的魔术标记检测LIKE语句,并重写SQL以使用CTX CONTAINS调用。
一个缺点是不能以简单的方式获得分数,但可以通过分数增强驾驶员的排序。随意编辑代码:-)
我假设有可能移植到休眠,假设有一个类似的机制来调整数据库查询到一个特定的数据库。
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实际上有一个'包含'操作符,据推测为Lucene后端,jpa和sql后端生成一个'like'语句。
我还没有想出一个重载contains操作符的方法,以便它可以被使用。 (除了重写代码之外,自从我使用与WebSphere捆绑在一起的版本后,我无法做到这一点)。
因此,我使用一个小的静态方法,以使其在使用QuertyDSL时看起来很好。
// x.where(c.custName.like(CTX.contains("omg near ponies"))));
它甚至会更好,如果JPQL可以提供全文搜索引擎的一些抽象(或插件)...
10
标准支持功能()API,允许数据库功能,通过调用名称。
qb.gt(qb.function("CONTAINS", root.get("name"), qb.parameter("name"), qb.literal(1)), 1)
EclipseLink还使用FUNC关键字支持JPQL。
相关问题
- 1. JPA Criteria API查询中的字符串
- 2. 使用JPA Criteria API查询Enum的ElementCollection
- 3. JPA命名查询vs Criteria API?
- 4. JPA Criteria构建器IN子句查询
- 5. JPA 2 + Criteria API - 定义子查询
- 6. 使用Criteria API创建查询(JPA 2.0)
- 7. 如何使用JPA Criteria查询编写此查询?
- 8. JPA 2.0,Criteria API,子查询,in子查询
- 9. Oracle + JPA - 使用INTERVAL查询
- 10. JPA Criteria API for FROM子句和FROM子句中的子查询
- 11. SQL查询过于复杂以便在JPA Criteria API中显示?
- 12. JPA Criteria Api - 不在关系实体中查询
- 13. NHibernate Criteria查询楼
- 14. JPA CRITERIA查询通过加入列的顺序
- 15. 来自Hibernate的JPA样式Criteria/CriteriaBuilder查询会话
- 16. JPA Criteria API任意数量的连接/子查询
- 17. 使用Criteria API的动态JPA 2.0查询
- 18. JPA Criteria查询API和两列的订单
- 19. 使用JPA Criteria-API
- 20. JPA Criteria API加入
- 21. JPA/Hibernate Criteria API JOIN
- 22. 使用JPA Criteria-API
- 23. 如何添加到Spring/Hibernate架构创建JPA 2 Criteria查询?
- 24. 如何使用Criteria子句进行JPA查询?
- 25. 如何使用JPA Criteria Builder编写查询(包括子查询和存在)
- 26. 对于JPA查询设置oracle NLS_LANG
- 27. NHibernate和Criteria或NPersistence与其他查询
- 28. JPA Criteria API group_concat用法
- 29. JPA Criteria Builder:如何将ArrayList传递给Oracle函数?
- 30. JPA:转换SQL查询JPA查询
所以我想我不得不求助于JPA本地查询使用字符串连接和放弃类型安全。哎哟。 – Ryan