में ओरेकल टेक्स्ट मानदंड क्वेरी ओरेकल टेक्स्ट के कथन का उपयोग करके जेपीए मानदंड क्वेरी निष्पादित करना संभव है, और यदि ऐसा है तो कैसे?जेपीए
जेपीए
उत्तर
संदेह है। एपीआई सभी आरडीबीएमएस भर में है, और की तरह "की तरह"/"SUBSTRING" जो जब एक पाठ स्तंभ के लिए Oracle पर इस्तेमाल किया, लेकिन फिर वे सिर्फ मानक एसक्यूएल का उपयोग कर सकते है कि फार्म के बारे में कुछ करने के लिए मैप किया जा सकता है कुछ निर्माणों प्रदान करता है। उस
पर जोर देने का कोई मानक-अनुपालन तरीका नहीं है, मैंने ओपनजेपीए के लिए ओरेकलटेक्स्ट डिक्शनरी लिखा है, जो सामान्य 'जैसे' ऑपरेटरों को 'शामिल' ऑपरेटर में परिवर्तित करता है, जब तर्क "जादुई" मार्कर के साथ उपसर्ग होता है।
इस तरह, यह ओरेकल पाठ के साथ उपयोग करने के लिए QueryDSL या मानदंड भाषा (या JPQL) संभव है।
शब्दकोश तर्क में एक जादू मार्कर के साथ बयान की तरह का पता लगाता है, और SQL का पुनर्लेखन एक CTX शामिल हैं कॉल उपयोग करने के लिए।
एक दोष यह है कि स्कोर एक सरल तरीके से सुलभ नहीं है, लेकिन यह स्कोर से ऑर्डर करने के लिए चालक को बढ़ाने के लिए संभव हो जाएगा। कोड को संपादित करने के लिए स्वतंत्र महसूस करें :-)
मुझे लगता है कि पोर्ट को हाइबरनेट करने के लिए संभव है, मान लें कि डेटाबेस क्वेरी को एक विशिष्ट डीबी में ट्यून करने के लिए एक समान तंत्र है।
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)
एसक्यूएल
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 वास्तव में करता है माना जाता है कि ल्यूसीन बैकएंड के लिए एक 'कंटेनेंस' ऑपरेटर है, जिसके लिए जेपीए और एसक्यूएल बैकएंड्स 'जैसे' कथन उत्पन्न करते हैं।
मैं अधिक भार, ऑपरेटर शामिल हैं इतना है कि यह किया जा सकता है की एक तरीका खोज निकाला नहीं किया है। (कोड को फिर से लिखने के अलावा, जो मैं नहीं कर सकता क्योंकि मैं वेबस्पेयर के साथ बंडल किए गए संस्करण का उपयोग कर रहा हूं।)
तो, मैं 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 कीवर्ड का उपयोग करके जेपीक्यूएल में इसका समर्थन करता है।
तो मुझे लगता है कि मुझे स्ट्रिंग कॉन्सटेनेशन और फोर्गो टाइप सुरक्षा का उपयोग करके जेपीए मूल क्वेरी का सहारा लेना होगा। आउच। – Ryan