I have following query which select from employee table where name is "max" and ID not in 123 and 444.
Not in IDs can grow in future. But I am receiving error as
Error
( 8023): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: DatabaseException(near "?": syntax error (code 1 SQLITE_ERROR): , while compiling:
Query
List<String> a = [];
a.add("123");
a.add("444");
var table = await mydb.rawQuery(
"SELECT value from employee WHERE employeename = ? AND id NOT IN ? ORDER BY timestamp DESC",
["max", a]);
If the LIST is unpredictable, one way is that you can use JOIN to create your select statement with required value of NOT IN. Below is one sample.
void main() {
List<String> a = [];
a.add("123");
a.add("444");
var select =
'SELECT value from employee WHERE employeename = ? AND id NOT IN (\'' +
(a.join('\',\'')).toString() +
'\') ORDER BY timestamp DESC';
var table = await mydb.rawQuery(select, ["max"]);
}
If you print the variable select you will get
SELECT value from employee WHERE employeename = ? AND id NOT IN ('123','444')
ORDER BY timestamp DESC.
Then you can pass the above statement to rawquery and get your result.
P.S:Use your single quote and double quote accordingly.
I'd go for #arun-palanisamy 's solution, see his comment. Props go to him. I just tried the following -- with Groovy/Postgres, but the error seems to be the same, so you might want to give it a try:
String[] a = ['123', '444']
// your code, throws 'ERROR: syntax error at or near "$2"':
// def table = sql.execute("SELECT value from employee WHERE employeename = ? AND id NOT IN ? ORDER BY timestamp DESC", ["max", a])
// code of arun-palanisamy, compiles:
def table = sql.execute("SELECT value from employee WHERE employeename = ? AND id NOT IN (${a.join(', ')}) ORDER BY timestamp DESC", ["max", a])
Side notes:
You might want to try a different type for a, such as Array in my code, or even a HashMap.
There are examples (like here) where the number of ? are generated dynamically.
Update: Go for this answer, we posted simultaneously
Related
I have an existing linq query which gets some data into a view model object. This is working fine.
I want to add a new property for data from child table which will have column values from a child table in a comma separated string format.
Problem: I am not able to concatenate the results using string.join
Simplified version of tables showing only relevant fields
part
id
part number
1
ABC1
2
DEF1
vendor
id
vendorname
1
acme
2
john
vendor part name (vendor specific part number)
partid
vendorid
partname
1
1
GDSE-553-32
1
2
JWWVV-HH-01
simplified version of query
result = (from p in DBContext.Parts.Where(w => w.EquipmentId == eId)
select new PartModel
{
Id = p.Id,
Number = p.PartNumber,
VendorPartNames= String.Join(",", DBContext.VendorPartName.Where(w => w.PartId == p.Id).Select(s => s.PartName))//this line causes exception (shown below)
});
Exception:
LINQ to Entities does not recognize the method 'System.String Join(System.String, System.String[])' method, and this method cannot be translated into a store expression.
Please note: the actual query has some joins and other columns, so please dont suggest solutions that requires joins.
If I change the "VendorPartName" to a List type , I can get the results without any problems.
My only problem is in "How to convert the results for "VendorPartName" property to a comma separated strings?"
eg: based on sample table data provided, it should be
GDSE-553-32, JWWVV-HH-01
Entity Framework does not support String.Join() method.
So, what we can do is to fetch VendorPartNames as a string collection and then we can later separate it with ,.
Note: For this, we would first use an anonymous object and later convert it to PartModel.
So your query would look like this:
var parts = DBContext.Parts
.Where(w => w.EquipmentId == eId)
.Select(p => new {
Id = p.Id,
Number = p.PartNumber,
VendorPartNames = p.VendorPartName.Select(n => n.PartName)
}).ToList();
var result = parts.Select(i => new PartModel {
Id = i.Id,
Number = i.Number,
VendorPartNames = String.Join(",", i.VendorPartNames)
}).ToList();
I created a a query to only get 4 items from a row in a table which does not include the column cloth style, so i understand why i get the error, but how can i tell Spring Jpa or JPA it is on purpose. and i just want the id, name and color table ?
this is my code:
#RequestMapping(value = "/query/material",method = RequestMethod.GET)
public String QueryMaterialTable(HttpServletRequest request){
DataTableRequest<Material> dataTableInRQ = new DataTableRequest<Material>(request);
PaginationCriteria pagination = dataTableInRQ.getPaginationRequest();
String baseQuery = "SELECT id as id, time as time, name as name, color as color, price as price, (SELECT COUNT(1) FROM MATERIAL) AS totalrecords FROM MATERIAL";
String paginatedQuery = AppUtil.buildPaginatedQuery(baseQuery, pagination);
System.out.println(paginatedQuery);
Query query = entityManager.createNativeQuery(paginatedQuery, Material.class);
#SuppressWarnings("unchecked")
List<Material> materialList = query.getResultList();
DataTableResults<Material> dataTableResult = new DataTableResults<Material>();
dataTableResult.setDraw(dataTableInRQ.getDraw());
dataTableResult.setListOfDataObjects(materialList);
if (!AppUtil.isObjectEmpty(materialList)) {
dataTableResult.setRecordsTotal(String.valueOf(materialList.size())
);
if (dataTableInRQ.getPaginationRequest().isFilterByEmpty()) {
dataTableResult.setRecordsFiltered(String.valueOf(materialList.size()));
} else {
dataTableResult.setRecordsFiltered(String.valueOf(materialList.size()));
}
}
return new Gson().toJson(dataTableResult);
}
If I got the question right, your problem is with the following two lines:
Query query = entityManager.createNativeQuery(paginatedQuery, Material.class);
List<Material> materialList = query.getResultList();
You have various options to fix this:
provide a complete column list, i.e. provide the missing column in the SQL statement and just make them NULL;
Don't use Material but a new class that has the matching attributes.
Don't use a native query but JPQL and a constructor expression.
Use a ResultTransformer.
Use Spring Data and a Projection.
Use a Spring JdbcTemplate.
I have the following entity code where i want to return a formatted string based on a custom a function that return a string:
var query =
from a in db.Authors
join b in db.Books
on a.id equals b.atuhorId into ab
from item in ab.DefaultIfEmpty()
select new
{
id = a.id,
authorName= a.name,
bookName = b.name,
formatted_book = item.id != null ? model.getFormatedBook(item.id) : "N/A",
},
};
But i got an error like mentioned in my post title.
Is there a cast that i can put inside my entity code for the getFormatedBook(item.id) ? I tried getFormatedBook(item.id).ToString() but with no success
Thanks
LINQ to Entity is unable to call outside methods as a part of a query. Take a look at this answer: https://stackoverflow.com/a/12641286/1202275 for possible workarounds.
Say I get an entity from database, employee, and it has 3 attributes :
1.name(String)
2.id(String)
3.department(String).
Now I want to do a group-function query like: select e.department, count(e) from employee e group by e.department. I'm using EntityManager to create an executable query but question is no such entity fits the result, what should I do to do such a query and obtain the result?
Your query will return results like this:
Department Count
Dept1 10
Dept2 20
Assuming you have a ResultSet object:
while(rs.next()){
String dept = rs.getString(1); //You can use column name if its defined
int count = rs.getInt(2);
}
select e.department, count(e) from employee e group by e.department
This jpql will give result as Object[] .
Then cast the result to required object.
for (Object[] o : resultList) {
String department = (String) o[0];
int e = (Integer) o[1];
System.out.println(department + " : " + e);
}
I think this will help you.
hey i'm looking for way to search for text pattern (in jpa) and to sort the result, first all the result starting with this string and then all other result.
i have found Mysql order by using search string to get the answer for mysql
most of the answers use union(which does not exist in jpa) and force to query the db or open a view for that. (ordering from code is not that good solution since we use paging to get part of the result as the result size can be really big)
One solution i like from the link above is :
select * from employee where name like '%ani%' order by locate('ani', name) asc, name asc
source
This seems to me very clear but i'm not sure how to convert it to jpa. seems like Order object is not able to get locate output
any ideas will be welcome
Thanks!
Alon
EDIT:
thanks for reply. i'm tring to achive the same with jpa critiera
Iterator<Order> sortingIter = page.getSort().iterator();
ArrayList<javax.persistence.criteria.Order> order = new ArrayList<javax.persistence.criteria.Order>();
String fieldName;
while (sortingIter.hasNext()) {
Order sort = sortingIter.next();
fieldName = sort.getProperty();
order.add(sort.getDirection() == Sort.Direction.ASC ? cb
.asc(keyword.get(fieldName)) : cb.desc(keyword
.get(fieldName)));
}
while the above works well. i cannot add the following line to the code. seems like Order object doesnt like them
Expression<String> fieldValue = keyword.get(fieldName);
order.add(cb.locate(fieldValue,key));
EDIT 2:
tried
order.add(new javax.persistence.criteria.Order() {
#Override
public javax.persistence.criteria.Order reverse() {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean isAscending() {
// TODO Auto-generated method stub
return true;
}
#Override
public Expression<?> getExpression() {
// TODO Auto-generated method stub
return cb.locate(fieldValue,key);
}
});
jpa doesn't complain but the query does not get the right order
EDIT 3:
Found my mistake!
The key value i was passing above already contained "%" and both sides... so locate did not work properly.
now i'm getting some weird behavior on some special chars:if - for example - i have the word Ghurabā the query like %ba% will find it. but, it seems that locate(Ghurabā,ba) will return 0 - meaning as pattern was not found in string any idea how to overcome this issue?
seems like this is not only jpa but also mysql behavior.
SELECT *
FROM `keywords`
WHERE name LIKE '%ba%'
ORDER BY LOCATE( 'ba', name ) , name
LIMIT 0 , 30
will return the next result
Ghurabā'
Khuṭabā'
qabā\
Ribāṭ
ba'urchi (cook)
Baghdad
...
note that it does work for "regular english characters" but there is a mismatch between the like and the locate function
Using Collcation: utf8_general_ci (got the same result with utf_unicode_ci)
This does not makes any complain.
String jpql = "select e from Employee e where e.name like '%ani%' order by locate('ani', e.name) asc, e.name asc";
TypedQuery<Employee> query2 = em.createQuery(jpql ,Employee.class);
And this is the translation that hibernate does.
Hibernate: select employee0_.id as id1_2_, employee0_.address_id as
address5_2_, employee0_.DEPT_ID as DEPT6_2_, employee0_.manager_id as
manager7_2_, employee0_.name as name2_2_, employee0_.salary as
salary3_2_, employee0_.startDate as startDat4_2_ from Employee
employee0_ where employee0_.name like '%ani%' order by locate('ani',
employee0_.name) asc, employee0_.name asc
Using some data as the link you mention.
Employee 10: name: anil, salary: 59000,
Employee 1: name: anirudha, salary: 55000,
Employee 5: name: rani,
Employee 7: name: Stephanie, salary: 54000,
{anil,anirudha,rani, ...}
Same problem using CriteriQuery solution
Ok, you own me some points for this =)
Hibernate: select employee0_.id as id1_2_, employee0_.address_id as address5_2_, employee0_.DEPT_ID as DEPT6_2_, employee0_.manager_id as manager7_2_, employee0_.name as name2_2_, employee0_.salary as salary3_2_, employee0_.startDate as startDat4_2_ from Employee employee0_ where employee0_.name like ? order by locate(?, employee0_.name) asc, employee0_.name asc
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
Root<Employee> root = cq.from(Employee.class);
cq.where(cb.like(root.<String>get("name"), "%ani%"));
cq.orderBy(cb.asc(cb.locate(root.<String>get("name"), "ani")), cb.asc(root.get("name")));
TypedQuery<Employee> query2 = em.createQuery(cq);
printList(query2.getResultList());
Try the above it should work.
Employee 10: name: anil, salary: 59000,
Employee 1: name: anirudha, salary: 55000,
Employee 5: name: rani,
Employee 7: name: Stephanie, salary: 54000,
Check this out if you think ?(question mark) is not correct in the query.
http://webdev.apl.jhu.edu/~jcs/ejava-javaee/coursedocs/605-784-site/docs/content/html/jpa-query-criteria-function.html#jpa-query-criteria-function-string-locate