for some reason i can't tell, there is exception when i try to get a list from CriteriaQuery using subquery. some one please help!!!
here is the code:
public String[] getProductsDistinctBySubQueriesName(String category) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Tuple> criteria = builder.createTupleQuery();
//subquery
Subquery<Integer> subqueries = criteria.subquery(Integer.class);
Root<Productscategory> productCategory = subqueries.from(Productscategory.class);
subqueries.select(productCategory.<Integer>get("productscategoryid"))
.where(builder.equal((productCategory.<String>get("productcatgoryname")), category));
//outerquery
Root<Products> root = criteria.from(Products.class);
criteria.multiselect(root.get(Products_.productname)).distinct(true)
.where(builder.in(root.get("productscategoryid")).value(subqueries));
List<Tuple> tupleResult = em.createQuery(criteria).getResultList(); // the exception is thrown here
String[] arrayProducts = new String[tupleResult.size()];
for (int i = 0; i < tupleResult.size(); i++) {
arrayProducts[i] = (String) tupleResult.get(i).get(0);
}
return arrayProducts;
}
here is the exception
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = 'Pri' at line 1
Error Code: 1064
Error Code: 1064
Call: SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))
bind => [1 parameter bound]
Call: SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))
bind => [1 parameter bound]
Query: TupleQuery(referenceClass=Products sql="SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))")
Query: TupleQuery(referenceClass=Products sql="SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))")
at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:378)
at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:378)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260)
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:469)
at com.inventory.service.ProductsServices.getProductsDistinctBySubQueriesName(ProductsServices.java:112)
at com.inventory.service.ProductsServices.getAllByName(ProductsServices.java:211)
at com.inventory.server.InventorySocketRequest.getServiceClass(InventorySocketRequest.java:77)
at com.inventory.server.InventorySocketRequest.run(InventorySocketRequest.java:44)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = 'Pri' at line 1
Error Code: 1064
Call: SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))
bind => [1 parameter bound]
Query: TupleQuery(referenceClass=Products sql="SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:682)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:694)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2738)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllReportQueryRows(ExpressionQueryMechanism.java:2675)
at org.eclipse.persistence.queries.ReportQuery.executeDatabaseQuery(ReportQuery.java:848)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127)
at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:403)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1215)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1740)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258)
... 5 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = 'Pri' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1053)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2794)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1007)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:642)
... 24 more
Try to use this query instead of yours, this works perfectly with EclipseLink provider, not sure what your query is not working in eclipselink but works in hibernate, I tested the query below and you will be able to select Products based on a ProductCategoryName.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaQuery");
EntityManager em = emf.createEntityManager();
String category = "cat2";
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Products> query = builder.createQuery(Products.class);
Root<Products> products = query.from(Products.class);
Subquery<Productscategory> squery = query.subquery(Productscategory.class);
Root<Productscategory> productCategoryRoot = squery.from(Productscategory.class);
Join<Productscategory, Products> join = productCategoryRoot.join("productsCollection");
squery.select(productCategoryRoot)
.where(builder.equal(join, products), builder.equal(productCategoryRoot.get("productcatgoryname"), category));
query.where( builder.exists(squery));
List<Products> productList = em.createQuery(query).getResultList();
for (Products product : productList) {
System.out.println(product);
}
In which category is the name of the category you are trying to search..
This solved the problem =).. If this works, don't forget to accept the answer XD.
Related
I want to combine the results of the queries of two different models with union, but sql code parts are different, and Django throws an exception:
Unable to get repr for <class 'django.db.models.query.QuerySet'>
django.db.utils.ProgrammingError: UNION types numeric and character varying cannot be matched
LINE 1: ...order"."update_date", "core_filled"."status", "core_trig..
custom_qs = active_qs.annotate(**{'order_numberx': F('order_number'),
'condition_side': Value('GTE', output_field=CharField()),
}).values("order_number", "account_id",
"order_type", "price",
"buy_sell", "status",
"add_date", "update_date",
"status", "condition_side",
"total_price")
filled_qs = trigger_qs.annotate(**{'order_numberx': F('order_number'),
'total_price': Value(0, output_field=DecimalField())
}).values("order_number", "account_id",
"order_type", "price",
"buy_sell", "status",
"add_date", "update_date",
"status", "condition_side",
"total_price")
orders_qs = active_qs.union(trigger_qs)
SQL QUERY
(SELECT "core_custom"."order_number", "core_custom"."account_id", "core_custom"."order_type", "core_custom"."market_code", "core_custom"."channel_code", "core_custom"."price", "core_custom"."volume", "core_custom"."volume_executed", "core_custom"."buy_sell", "core_custom"."status", "core_custom"."add_date", "core_custom"."update_date", "core_custom"."client_id", "core_custom"."post_only", "core_custom"."status", "core_custom"."total_price", GTE AS "condition_side"
FROM "core_custom"
WHERE ("core_custom"."account_id" = 1549 AND "core_custom"."status" IN (N, P)))
UNION
(SELECT "core_filled"."order_number", "core_filled"."account_id", "core_filled"."order_type", "core_filled"."market_code", "core_filled"."channel_code", "core_filled"."price", "core_triggerorder"."volume", "core_filled"."volume_executed", "core_filled"."buy_sell", "core_filled"."status", "core_filled"."add_date", "core_filled"."update_date", "core_filled"."client_id", "core_filled"."post_only", "core_filled"."status", "core_filled"."condition_side", 0 AS "total_price"
FROM "core_filled"
WHERE ("core_triggerorder"."account_id" = 1549 AND "core_filled"."status" = N))
How can I control order of columns in sql query generated by ORM?
I have the following Named query on my spring-data repository:
#Query("FROM Pedido p JOIN FETCH p.status ps WHERE ps.status IN (?1) AND ps.id IN (SELECT MAX(ps2.id) FROM PedidoStatus ps2 GROUP BY ps2.pedido)")
I'm trying to achieve the same result using the Criteria API and spring-data Specifications, this is what I have so far:
public static Specification<Pedido> byUltimoStatus(final List<PedidoStatus.StatusPedido> ultimoStatus) {
return new Specification<Pedido>() {
public Predicate toPredicate(Root<Pedido> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Expression<PedidoStatus.StatusPedido> status = root.join("status").get("status");
Predicate predicateByStatus = status.in(ultimoStatus);
final Subquery<Long> subQuery = query.subquery(Long.class);
final Root<PedidoStatus> ps = subQuery.from(PedidoStatus.class);
Expression<Long> psId= ps.get("id");
Expression<Long> maxId = builder.max(psId);
subQuery.select(maxId);
subQuery.groupBy(ps.get("pedido").get("id"));
Predicate predicateByUltimoStatus = builder.in(root.join("status").get("id")).value(subQuery);
return builder.and(predicateByStatus, predicateByUltimoStatus);
}
};}
It's still not working, looks like there is an extra
INNERJOIN PedidoStatus
in the result query.
This is the result of the #Query:
select ... from Pedido pedido0_ inner join PedidoStatus status1_ on pedido0_.id=status1_.pedido where (status1_.status in (? , ?)) and (status1_.id in (select max(pedidostat2_.id) from PedidoStatus pedidostat2_ group by pedidostat2_.pedido))
And this is the result of the Criteria API:
select ... from Pedido pedido0_ inner join PedidoStatus status1_ on pedido0_.id=status1_.pedido inner join PedidoStatus status2_ on pedido0_.id=status2_.pedido where (pedido0_.id is not null) and status1_.status IN (?, ?) and (status2_.id in (select max(pedidostat3_.id) from PedidoStatus pedidostat3_ group by pedidostat3_.pedido))
Knowing that this is a very old question, it looks to me like the reason for the duplicate INNERJOIN in the query generated by a CriteriaQuery is that the code building the query, does actually invoke root.join("status") twice. The result of the first invocation should be saved into a local variable, so you can reuse it, instead of joining twice.
First you do:
Expression<PedidoStatus.StatusPedido> status = root.join("status").get("status");
And later you do:
Predicate predicateByUltimoStatus = builder.in(root.join("status").get("id")).value(subQuery);
In database I have partitioning table by column 'status' for better performance. My database administrator ask me about put in query value for that column directly in sql (not bind by parameter).
I can change binding by set hint QueryHints.BIND_PARAMETERS on false, but then all parameters are inside sql.
Can I set not bind only on 'status' parameter ?
Example result when BIND_PARAMETERS = true
SELECT t0.* FROM S_JOBS_ORG_UNIT_CFG t0
WHERE ((((t0.ORG_ID = ?) AND (t0.SCHEDULER_NEXT_ACTIVATION < SYSDATE)) AND (t0.ACTIVE = ?))
AND NOT EXISTS (SELECT ? FROM S_JOBS t1 WHERE (((t1.ORDER_ID = t0.ORDER_ID) AND (t1.ORG_ID = t0.ORG_ID)) AND NOT ((t1.STATUS = ?)))) )
bind => [472100, Y, 1, E]
and result when BIND_PARAMETERS = false
SELECT t0.* FROM S_JOBS_ORG_UNIT_CFG t0
WHERE ((((t0.ORG_ID = 472100) AND (t0.SCHEDULER_NEXT_ACTIVATION < SYSDATE)) AND (t0.ACTIVE = Y))
AND NOT EXISTS (SELECT 1 FROM S_JOBS t1 WHERE (((t1.ORDER_ID = t0.ORDER_ID) AND (t1.ORG_ID = t0.ORG_ID)) AND NOT ((t1.STATUS = E)))) )
Code:
Query jobOrgUnitCfgQuery = entityManager.createQuery(
"SELECT c FROM JobOrgUnitCfg c WHERE c.orgId = :orgId and c.schedulerNextActivation < current_timestamp and c.active = :active and " +
" not exists (SELECT j FROM Job j WHERE j.orderId = c.orderId and j.orgId = c.orgId and j.status <> 'E')");
jobOrgUnitCfgQuery.setParameter("orgId", orgId);
jobOrgUnitCfgQuery.setParameter("active", Boolean.TRUE);
return jobOrgUnitCfgQuery.getResultList();
I think your best bet is just to programmatically build your query like you're doing with a hard coded status and escape the other paramaters manually to avoid SQL Injection.
I have a query
SELECT d.name, count(e.id) FROM department d LEFT OUTER JOIN employee e on e.department_id = d.id and e.salary > 5000
and how i can convert this to jpa
right now i have:
CriteriaQuery<Object[]> criteria = builder.createQuery(Object[].class);
Root<Department> root = criteria.from(Department.class);
Path<String> name = root.get("name");
Expression<Long> empCount = builder.count(root.get("employees").get("id"));
criteria.multiselect(name,empCount);
TypedQuery<Object[]> query = em.createQuery(criteria);
I simplified both examples by removing ordering and grouping
can anyone tell me how i can modifie my jpa code to get same reslults like from my sql query
thanks in advance
You're not far from the result. The problem is that, AFAIK, you can't add any restriction on the on clause, using JPA. So the query wil have to be rewritten as
SELECT d.name, count(e.id) FROM department d
LEFT OUTER JOIN employee e on e.department_id = d.id
where (e.id is null or e.salary > 5000)
Here is the equivalent of this query not tested):
CriteriaQuery<Object[]> criteria = builder.createQuery(Object[].class);
Root<Department> root = criteria.from(Department.class);
Path<String> name = root.get("name");
Join<Department, Employee> employee = root.join("employees", JoinType.LEFT);
Expression<Long> empCount = builder.count(employee.get("id"));
criteria.multiselect(name,empCount);
criteria.where(builder.or(builder.isNull(employee.get("id")),
builder.gt(employee.get("salary"), 5000)));
TypedQuery<Object[]> query = em.createQuery(criteria);
My Requirement is to write a sql query to get the sub-region wise (fault)events count that occurred for the managedobjects. My database is postgres 8.4. Let me explain using the table structure.
My tables in django:
Managedobject:
class Managedobject(models.Model):
name = models.CharField(max_length=200, unique=True)
iscontainer = models.BooleanField(default=False,)
parentkey = models.ForeignKey('self', null=True)
Event Table:
class Event(models.Model):
Name = models.CharField(verbose_name=_('Name'))
foid = models.ForeignKey(Managedobject)
Managedobject Records:
NOC
Chennai
MO_1
MO_2
MO_3
Mumbai
MO_4
MO_5
MO_6
Delhi
Bangalore
IP
Calcutta
Cochin
Events Records:
event1 MO_1
event2 MO_2
event3 MO_3
event4 MO_5
event5 MO_6
Now I need to get the events count for all the sub-regions. For example,
for NOC region:
Chennai - 3
Mumbai - 2
Delhi - 0
Bangalore - 0
So far I am able to get the result in two different queries.
Get the subregions.
select id from managedobject where iscontainer = True and parentkey = 3489
For each of the region (using for loop), get the count as follows:
SELECT count(*)
from event ev
WHERE ev.foid
IN (
WITH RECURSIVE q AS (
SELECT h
FROM managedobject h
WHERE parentkey = 3489
UNION ALL
SELECT hi
FROM q
JOIN managedobject hi
ON hi.parentkey = (q.h).id
)
SELECT (q.h).id FROM q
)
Please help to combine the queries to make it a single query and for getting the top 5 regions. Since the query is difficult in django, I am going for a raw sql query.
I got the query:
WITH RECURSIVE q AS (
SELECT h,
1 AS level,
id AS ckey,
displayname as dname
FROM managedobject h
WHERE parentkey = 3489
and logicalnode=True
UNION ALL
SELECT hi,
q.level + 1 AS level,
ckey,
dname
FROM q
JOIN managedobject hi ON hi.parentkey = (q.h).id
)
SELECT count(ckey) as ccount,
ckey,
dname
FROM q
JOIN event as ev on ev.foid_id = (q.h).id
GROUP BY ckey, dname
ORDER BY ccount DESC
LIMIT 5