count(distinct( with an EntityManager - java

i have an issue with my EntityManager.
Comparing, core-SQL with java EntityManager, i do not observe the sames comportments.
in core-SQL (OK)
select count (distinct p.product_id) from product p ;
equivalent with an EntityManager (OK)
Query c = entityManager.createQuery("select
count(distinct(p.productId))
from product p");
but now, with two arguments, i got an issue :
in core-SQL (OK)
select count (distinct (p.product_id , p.product_name)) from product p ;
equivalent with an EntityManager = KO !!!!
Query c = entityManager.createQuery("select
count(distinct(p.productId, p.productName))
from product p");
EntityManager does not accept two arguments in the distinct clause.
i got an exception
antlr.NoViableAltException: unexpected AST node: {vector}

Related

Pagination on Native sql query gives : unexpected token: ON

While writing a pagination query in repository as below code segment, I'm getting following error.
Code
#Repository
public interface Aaaa extends PagingAndSortingRepository<TxnDealerInventoryItem, Long> {
#Query(value = "SELECT EM.PART_NO, EM.PART_NAME FROM TXN_DEALER_INVENTORY_ITEM E INNER JOIN MST_PRODUCT EM ON E.PRODUCT_ID = EM.PRODUCT_ID WHERE E.ACCOUNT_ID= :accountId AND EM.ALLOW_SERIAL_NUM = :isSerialized ORDER BY ?#{#pageable}",
countQuery = "SELECT COUNT(*) FROM TXN_DEALER_INVENTORY_ITEM E INNER JOIN MST_PRODUCT EM ON E.PRODUCT_ID = EM.PRODUCT_ID WHERE E.ACCOUNT_ID= :accountId AND EM.ALLOW_SERIAL_NUM = :isSerialized",
nativeQuery = true)
Page<Object[]> getNonSerializedDeviceList(#Param("accountId") Long accountId, #Param("isSerialized") String isSerialized, Pageable pageable);
}
Error
HQL: SELECT COUNT(*) FROM TXN_DEALER_INVENTORY_ITEM E INNER JOIN MST_PRODUCT EM ON E.PRODUCT_ID = EM.PRODUCT_ID WHERE E.ACCOUNT_ID= :accountId AND EM.ALLOW_SERIAL_NUM = :isSerialized
2023-02-10 18:52:52,753 ERROR [org.hibernate.hql.internal.ast.ErrorCounter] (http-/127.0.0.1:8881-1) line 1:76: unexpected token: ON
Native Query doesn't have any error when run from sql developer.
Framework versions are as follows, Unfortunately I'cant update these any further as there are limitations in deployment environment. You inputs are highly welcome on this !!
<spring.version>4.3.30.RELEASE</spring.version>
<spring.data.version>1.11.23.RELEASE</spring.data.version>
<hibernate.version>4.2.18.Final</hibernate.version>
PS : for testing purpose when I change the SQL to a very basic like a select *, It gives following error.
org.hibernate.hql.internal.ast.QuerySyntaxException: TXN_DEALER_INVENTORY_ITEM is not mapped [SELECT COUNT(*) FROM TXN_DEALER_INVENTORY_ITEM E ]
Got the problem resolved by removing the count query and make the return type to a List of object Array instead of Page as below code segment.
#Repository
public interface Aaaa extends PagingAndSortingRepository<TxnDealerInventoryItem, Long> {
#Query(value = "SELECT EM.PART_NO, EM.PART_NAME FROM TXN_DEALER_INVENTORY_ITEM E INNER JOIN MST_PRODUCT EM ON E.PRODUCT_ID = EM.PRODUCT_ID WHERE E.ACCOUNT_ID= :accountId AND EM.ALLOW_SERIAL_NUM = :isSerialized ORDER BY ?#{#pageable}",
nativeQuery = true)
List<Object[]> getNonSerializedDeviceList(#Param("accountId") Long accountId, #Param("isSerialized") String isSerialized, Pageable pageable);
}
Finally having good old Paginations :) Thanks everyone who looked into this.

JPA Criteria API: select count(*) from subquery with joins and group by for pagination implementation

I want to implement a pagination feature in a list of products returned from database. So I need to known the total results of the query.
Database tables are:
PRODUCT TABLE
-----------------------------
ID NAME
-------------- --------------
1 Product 1
2 Product 2
PRODUCT SUPPLIER TABLE
--------------------------------------------
ID PRODUCT ID PRICE
-------------- -------------- --------------
1 1 35
2 1 30
3 2 70
4 2 75
The desire result is a list of products with the minimum price of the different suppliers.
Product 1 30
Product 2 70
Main query should be something like:
select p.name, min(ps.price) from product
inner join product_supplier ps on ps.product_id = p.id
group by p.name
So count query should be something like:
select count(*) from (
select p.name, min(ps.price) from product
inner join product_supplier ps on ps.product_id = p.id
group by p.name
)
Code I'am using to get paginated results is:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> tupleQuery = cb.createTupleQuery();
Root<product> product = tupleQuery.from(product.class);
Join<product, productSupplier> productSuppliers = product.join("productSuppliers");
tupleQuery.multiselect(
product,
cb.min(productSuppliers.get("price")).alias("price")
);
tupleQuery.groupBy(product);
tupleQuery.orderBy(cb.asc(product.get("name")));
TypedQuery<Tuple> query = entityManager
.createQuery(tupleQuery)
.setMaxResults(pageable.getPageSize())
.setFirstResult(Long.valueOf(pageable.getOffset()).intValue());
List<Tuple> products = query.getResultList();
for (Tuple productResult : products) {
Product product = productResult.get(product);
Double minPrice = (Double)productResult.get("price");
ProductDTO productDTO = new ProductDTO(product, minPrice);
}
But I'm not sure how to get count from the main query. Code I'm using is:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> countQuery = cb.createQuery(Long.class)
Root<Product> product = countQuery.from(Product.class);
Join<Product, ProductSupplier> productSuppliers = product.join("productSuppliers");
countQuery.groupBy(product);
countQuery.select(cb.count(product));
long count = entityManager.createQuery(countQuery).getSingleResult();
But it produces the following SQL:
select
count(product0_.id) as col_0_0_
from
pu_products product0_
inner join
pu_product_suppliers productsu1_
on product0_.id=productsu1_.product_id
group by
product0_.id
Returning more than one result, throwing the following exception:
org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 31
So I don't know how to get it work.
Thanks.
Seems that is not possible to do a select count (*) from from an aggregated query via Criteria API:
Discussion in discourse.hibernate.org
You can use a subquery only in your WHERE but not in the SELECT or FROM clause
So finally I've applied this solution found in this answer:
After build the query via Criteria API, get the final query string.
Wrap it with select count(*) from ({final_query_string}).
Create a Native Query with the result of wrapping the final query string with the select count (*) from.
Full code of this solution in this answer from #fliX.
Regards.
What about a namedquery like this one :
select count(distinct ps.product) from product_supplier ps where ps.price is not null

Hibernate SQLQuery neglecting aliasname

When i try to execute the following query in mysql , it works perfectly. But when we try it via Hibernate(3.2) ,hibernate is not differentiating m.NAME and o.NAME. It is returning the same result for both as m.NAME.
SELECT m.NAME, m.SCREENNAME, rm.ADDRESS, o.NAME FROM remoteunit rm LEFT JOIN mo m ON rm.MOID = m.ID JOIN overallcustomfields ocf ON m.ID = ocf.MOID LEFT JOIN organization o ON ocf.ORGID = o.ID WHERE m.DOMAINID = 2
Iam using the following code
Transaction transaction = session.beginTransaction();
SQLQuery query = session.createSQLQuery(queryString);
query.setLong("customId", customId);
remoteUnitList = (ArrayList<Object[]>)query.list();
transaction.commit();
Note: Forced to use SQLQuery in Hibernate since the columns are dynamically populated and more constraints.
Did you try SELECT m.NAME as m_name, o.NAME as o_name.... I faced the same problem and it went of with this change.

HQL right join empty list

I am using hql with hibernate. I've tried to write a query over three tables. The tables are Medientyp, RaumMedientyp and Raum. I wanna read all Medientyp's from the whole table and all RaumMedientyp's from a specific raumId.
The realtions between the tables are:
Medientyp 1 <--> mc RaumMedientyp mc <--> 1 Raum
I need all as RaumMedientyp Entity.
The query i tried is:
String hql = "from RaumMedientyp rm right join rm.medientyp m inner join rm.raum r where r.id = :raumId";
Query query = getSession().createQuery(hql);
query.setInteger(":raumId", raumId);
But if i'm executing
query.list();
i've got a empty list as return.

Java: Retrieve results from Persistence Query Language using List

Im querying a database using JPQL but I cannot retrieve the 'Report' table's rows using List. This is a section of my code:
...
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hibernate");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Query query = em.createQuery("SELECT r.title, r.company FROM Report as r");
List<Report> itemList = query.getResultList();
for (Report item : itemList)
{
System.out.println("Item: " + item.getCompany());
}
The output is:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to maps.Report at hello.Test.main(Unknown Source)
Java Result: 1
What am I doing wrong? Why I am not allowed to do the casting?
Your query doesn't select instances of Report. It selects two fields: r.title and r.company. In this case, JPA returns a list of Object[]. Each Object[] of the list contains two elements: the title and the company.
Use select r from Report r to select Report instances.
You need to create a TypedQuery.
String sql = "select r from Report r";
TypedQuery<Report> query = em.createQuery(sql, Report.class);
List<Report> reports = query.getResultList();

Categories