Dynamic JPQL query qith JOIN - jpa

Had to write a jpql query, based on the input need to add and condition and for some input had to need JOIN queries.
#Override
public List<IncidentHdr> fetchIncidents(IncidentHdrDto incidentHdrDto) {
StringBuilder query = new StringBuilder();
query.append(ReposJPQL.GET_INCIDENT_DETAILS);
Map<String, Object> parameters = new HashMap<String, Object>();
List<String> criteria = new ArrayList<String>();
if(incidentHdrDto.getIncidentId() > 0) {
criteria.add("inc.incidentId = :incidentId");
parameters.put("incidentId", incidentHdrDto.getIncidentId());
}
if(incidentHdrDto.getCatCode() > 0) {
criteria.add("inc.catCode = :catCode");
parameters.put("catCode", incidentHdrDto.getCatCode());
}
if(incidentHdrDto.getType != null) {
//here i need to generate a join query
//SELECT * FROM INCIDENT JOIN CATEGORY_MAST ON(INCIDENT.CAT_CODE = CATEGORY_MAST.CAT_CODE) WHERE CATEGORY_MAST.TYPE_CODE = 16
}
Query q = em.createQuery(query.toString());
logger.info("Get Incidents Query : "+query.toString());
for (Entry<String, Object> entry : parameters.entrySet()) {
q.setParameter(entry.getKey(), entry.getValue());
}
List<IncidentHdr> incidentHdrs = q.getResultList();
return incidentHdrs;
}
where as ReposJPQL is the base query which had a where condition.
public interface ReposJPQL {
public String GET_INCIDENT_DETAILS = "SELECT inc FROM IncidentHdr inc WHERE 1 = 1" ;
}

Related

How to write Criteria Query Builder for select all from List?

I need a query which will return only results which are having all values from the list.
Something like:
SELECT *
FROM ads_tags
WHERE tag_value("a", "b", "c");
I know that query is not good, but the point is that I want to filter ads but only ads which are having all tags from the list.
With my code, I am getting all ads that have at least one tag from the list. That is because I am using IN interface.
#Override
public List<AdsDTO> findAll(AdsSubGroup adssubgroup, Long userId, String status, String adsType,
String businessType, Long adsGroupId, String region, Integer fromPrice,
Integer toPrice, Boolean fixedPrice, Boolean freeDelivery, Boolean productWarranty,
Boolean urgentSales, Boolean hasImage, Integer pageNumber, Integer pageSize, List<String> tags) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Ads> query = builder.createQuery(Ads.class);
Root<Ads> ads = query.from(Ads.class);
// query.orderBy(builder.desc(ads.get("adsDate")));
List<Predicate> predicates = new ArrayList<>();
Join<Ads, JwtUser> adsUsersJoin = ads.join("users");
Join<Ads, AdsSubGroup> adsAdsSubGroupJoin = ads.join("adssubgroup");
Join<Ads, Tag> tagsJoin = ads.join("adsTags");
In<List<String>> in = builder.in(tagsJoin.get("name"));
if (tags != null && tags.size() > 0) {
// in.value(tags);
tags.forEach(tag - > in.value(tags));
/*
* for (String tag : tags) { in.value(tag);
*
* }
*/
predicates.add(in);
}
query.select(ads);
query.distinct(true);
query.where(predicates.toArray(new Predicate[0]));
if (!(pageNumber == null && pageSize == null)) {
TypedQuery<Ads> typedQuery = em.createQuery(query);
typedQuery.setFirstResult((pageNumber - 1) * pageSize);
typedQuery.setMaxResults(pageSize);
List<Ads> adsList = typedQuery.getResultList();
return AdsConverter.convertToAdsDTO(adsList);
} else {
List<Ads> adsList = em.createQuery(query).getResultList();
return AdsConverter.convertToAdsDTO(adsList);
}
}
What I need to write instead of In interface to get all ads which have ALL tags from the list, not at least one?
You need a join for each element of type Tag in your list.
It's hard to fix your code because it's not a minimal example, however the following should help:
CriteriaQuery<Ads> query = builder.createQuery(Ads.class);
Root<Ads> ads = query.from(Ads.class);
List<Predicate> predicates = new ArrayList<>();
for (String tag : tags) {
Join<Ads, Tag> tagsJoin = ads.join("adsTags");
predicates.add(builder.equal(tagsJoin.get("name"), tag));
}

Crm plugin update fails

I have created two new fields named "Price" for quote and quote product and I want to update the second every time I update the first.
Here is my code:
protected void ExecutePostAccountUpdateContacts(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
string oldPrice = "";
string newPrice = "";
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
var ServiceContext = new OrganizationServiceContext(service);
ITracingService tracingService = localContext.TracingService;
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
Entity preImageEntity = (context.PreEntityImages != null && context.PreEntityImages.Contains(this.preImageAlias)) ? context.PreEntityImages[this.preImageAlias] : null;
// get the post entity image
Entity postImageEntity = (context.PostEntityImages != null && context.PostEntityImages.Contains(this.postImageAlias)) ? context.PostEntityImages[this.postImageAlias] : null;
if (preImageEntity.Attributes.Contains("Price"))
{
oldPrice = (string)preImageEntity.Attributes["Price"];
}
if (postImageEntity.Attributes.Contains("Price"))
{
newPrice = (string)postImageEntity.Attributes["Price"];
}
if (newPrice != oldPrice)
{
try
{
//Create query to get the related contacts
var res = from c in ServiceContext.CreateQuery("Products")
where c["parentQuoteid"].Equals(entity.Id)
select c;
foreach (var c in res)
{
Entity e = (Entity)c;
e["Price"] = newPrice;
ServiceContext.UpdateObject(e);
}
ServiceContext.SaveChanges();
}
catch (FaultException ex)
{
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
}
}
}
Although you haven't asked a question, your query isn't quite right. So I am assuming your plugin fails when querying for product with a parentquoteid.
Not all linq operators are implemented, also , pass the entity logical name to the create query as a parameter, so instead of Products, just product. There is no out of the box field called parentquoteid, are you missing your custom attribute prefix?
var res = from c in ServiceContext.CreateQuery("product")
where c.GetAttributeValue<Guid>("new_parentquoteid") == entity.Id
select c;

How to use the QueryResult in Bluemix to get the BasicDocumentRevision

public List<Task> allTasks() {
int nDocs = this.mDatastore.getDocumentCount();
List<BasicDocumentRevision> all = this.mDatastore.getAllDocuments(0, nDocs, true);
List<Task> tasks = new ArrayList<Task>();
// Filter all documents down to those of type Task.
IndexManager im = new IndexManager(mDatastore);
List<Object> indexFields = new ArrayList<Object>();
indexFields.add("city");
indexFields.add("price");
indexFields.add("Area");
indexFields.add("Information");
indexFields.add("imagename");
// Create the index
im.ensureIndexed(indexFields);
Map<String, Object> query = new HashMap<String, Object>();
query.put("desc", "RESIDENTIAL PROPERTY");
QueryResult result = im.find(query);
for(BasicDocumentRevision rev :all) {
Task t = Task.fromRevision(rev);
if (t != null) {
tasks.add(t);
}
}
return tasks;
How do you use queryresult to get it stored in a task class object? I want my query to only be listed in listview. I am working on Bluemix, which uses Cloudant syn.
You can get the document revision from the QueryResult by iterating over the QueryResult Object like :
for(DocumentRevision rev : result){
Task t = Task.fromRevision(rev);
if(task != null)
tasks.add(t);
}

How to implement boolean retrieval using hitcollector in below scenario

I am running my code on TREC documents and right now implementing scoring scheme to get number of relevant documents. However now i want to implement boolean retrieval, I am trying to use HitCollector.
below is my code..
public class BatchSearch {
private BatchSearch() {}
/** Simple command-line based search demo. */
public static void main(String[] args) throws Exception {
String usage =
"Usage:\tjava BatchSearch [-index dir] [-simfn similarity] [-field f] [-queries file]";
if (args.length > 0 && ("-h".equals(args[0]) || "-help".equals(args[0]))) {
System.out.println(usage);
System.out.println("Supported similarity functions:\ndefault: DefaultSimilary (tfidf)\n");
System.exit(0);
}
String index = "index";
String field = "contents";
String queries = null;
String simstring = "default";
for(int i = 0;i < args.length;i++) {
if ("-index".equals(args[i])) {
index = args[i+1];
i++;
} else if ("-field".equals(args[i])) {
field = args[i+1];
i++;
} else if ("-queries".equals(args[i])) {
queries = args[i+1];
i++;
} else if ("-simfn".equals(args[i])) {
simstring = args[i+1];
i++;
}
}
Similarity simfn = null;
if ("default".equals(simstring)) {
simfn = new DefaultSimilarity();
} else if ("bm25".equals(simstring)) {
simfn = new BM25Similarity();
} else if ("dfr".equals(simstring)) {
simfn = new DFRSimilarity(new BasicModelP(), new AfterEffectL(), new NormalizationH2());
} else if ("lm".equals(simstring)) {
simfn = new LMDirichletSimilarity();
}
if (simfn == null) {
System.out.println(usage);
System.out.println("Supported similarity functions:\ndefault: DefaultSimilary (tfidf)");
System.out.println("bm25: BM25Similarity (standard parameters)");
System.out.println("dfr: Divergence from Randomness model (PL2 variant)");
System.out.println("lm: Language model, Dirichlet smoothing");
System.exit(0);
}
IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(index)));
IndexSearcher searcher = new IndexSearcher(reader);
searcher.setSimilarity(simfn);
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_41);
BufferedReader in = null;
if (queries != null) {
in = new BufferedReader(new InputStreamReader(new FileInputStream(queries), "UTF-8"));
} else {
in = new BufferedReader(new InputStreamReader(new FileInputStream("queries"), "UTF-8"));
}
QueryParser parser = new QueryParser(Version.LUCENE_41, field, analyzer);
while (true) {
String line = in.readLine();
if (line == null || line.length() == -1) {
break;
}
line = line.trim();
if (line.length() == 0) {
break;
}
String[] pair = line.split(" ", 2);
Query query = parser.parse(pair[1]);
doBatchSearch(in, searcher, pair[0], query, simstring);
}
reader.close();
}
/**
* This function performs a top-1000 search for the query as a basic TREC run.
*/
public static void doBatchSearch(BufferedReader in, IndexSearcher searcher, String qid, Query query, String runtag)
throws IOException {
// Collect enough docs to show 5 pages
TopDocs results = searcher.search(query, 1000);
ScoreDoc[] hits = results.scoreDocs;
HashMap<String, String> seen = new HashMap<String, String>(1000);
int numTotalHits = results.totalHits;
int start = 0;
int end = Math.min(numTotalHits, 1000);
for (int i = start; i < end; i++) {
Document doc = searcher.doc(hits[i].doc);
String docno = doc.get("docno");
// There are duplicate document numbers in the FR collection, so only output a given
// docno once.
if (seen.containsKey(docno)) {
continue;
}
seen.put(docno, docno);
System.out.println(qid+" Q0 "+docno+" "+i+" "+hits[i].score+" "+runtag);
}
}
}
The scoring is done in doBatchSearch and now i want to implement HitCollector here.

how could i use JPA criteria query api for joined columns?

i am new to JPA and i have a problem with it.
suppose that we have two tables which are related
by a ManytoOne association, which means that
table A stores a primary key of table B within it.
when these two tables are mapped to JPA entities
i have a problem for search on this situation.
i have used an existing code from richfaces demo, to handle filtering and sorting by using
JPA. this code is using input parameters to create criteria query.
this is the code:
private CriteriaQuery<T> createSelectCriteriaQuery() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(entityClass);
Root<T> root = criteriaQuery.from(entityClass);
if (arrangeableState != null) {
List<Order> orders = createOrders(criteriaBuilder, root);
if (!orders.isEmpty()) {
criteriaQuery.orderBy(orders);
}
Expression<Boolean> filterCriteria = createFilterCriteria(criteriaBuilder, root);
if (filterCriteria != null) {
criteriaQuery.where(filterCriteria);
}
}
return criteriaQuery;
}
protected Expression<Boolean> createFilterCriteriaForField(String propertyName, Object filterValue, Root<T> root, CriteriaBuilder criteriaBuilder) {
String stringFilterValue = (String) filterValue;
if (Strings.isNullOrEmpty(stringFilterValue)) {
return null;
}
stringFilterValue = stringFilterValue.toLowerCase(arrangeableState.getLocale());
Path<String> expression = root.get(propertyName);
Expression<Integer> locator = criteriaBuilder.locate(criteriaBuilder.lower(expression), stringFilterValue, 1);
return criteriaBuilder.gt(locator, 0);
}
private Expression<Boolean> createFilterCriteria(CriteriaBuilder criteriaBuilder, Root<T> root) {
Expression<Boolean> filterCriteria = null;
List<FilterField> filterFields = arrangeableState.getFilterFields();
if (filterFields != null && !filterFields.isEmpty()) {
FacesContext facesContext = FacesContext.getCurrentInstance();
for (FilterField filterField : filterFields) {
String propertyName = (String) filterField.getFilterExpression().getValue(facesContext.getELContext());
Object filterValue = filterField.getFilterValue();
Expression<Boolean> predicate = createFilterCriteriaForField(propertyName, filterValue, root, criteriaBuilder);
if (predicate == null) {
continue;
}
if (filterCriteria == null) {
filterCriteria = predicate.as(Boolean.class);
} else {
filterCriteria = criteriaBuilder.and(filterCriteria, predicate.as(Boolean.class));
}
}
}
return filterCriteria;
}
the code is okay, when i try to filter columns(not joined columns), but when i try to
query on joined column, the produced query is not correct and it throws exception.
so my question is that, how could i use JPA criteria query api, to filter rows by both
joined columns and non-joined coulmns.
thanks
I don't believe you can treat join columns like regular ones.
for example if you want to filter on id of B, you would have to create a join from A to B , then use B_.id to match values.
Shay