I have a named parameter in JPA typed query. I am setting a list of value in condition.
I am setting a list of integer, but when JPA converts typed query to corresponding sql query it is adding a to_number function and index of the table is not used.
List<Integer> studentIds=ArrayList<Integer>
//Student id is number in database and indexed.
query = "SELECT T.* FROM STUDENT WHERE STUDENT_ID IN (:studentIds)"
TypedQuery<Object[]> typedQuery = entityManager().createQuery( query, Object[].class);
typedQuery.setParameter("studentIds", studentIds);
The issue is when JPA generates the query it is adding to_number function to convert the list
SELECT * from student t4 where student_id in (?,?,?);
filter("T4"."student_id"=TO_NUMBER(:9) OR "T4"."student_id"=TO_NUMBER(:10) OR
"T4"."student_id"=TO_NUMBER(:11) OR "T4"."PRODUCT_SET_ID"=student_id(:12)
Any thoughts how to make sure JPA does not add a to_number function, so index will be used.
I had to use an array when I was passing values into a '.in' predicate. Try this:
List<Integer> studentIds=ArrayList<Integer>
Integer[] ids = new Integer[studentIds.size()];
ids = studentIds.toArray(ids);
//Student id is number in database and indexed.
query = "SELECT T.* FROM STUDENT WHERE STUDENT_ID IN (:studentIds)"
TypedQuery<Object[]> typedQuery = entityManager().createQuery( query, Object[].class);
typedQuery.setParameter("studentIds", ids);
Related
Suppose I have a table which contains all the accounts of user and type.
I want to make a Jpa Repository method which returns an array of total number of each type of user (USER, ADMIN, MASTER).
Here is how I did it in JpaRepository:
#Query(value="SELECT (SELECT COUNT(*) FROM account WHERE account_role='USER'),"
+ "(SELECT COUNT(*) FROM account WHERE account_role='ADMIN'),"
+ "(SELECT COUNT(*) FROM account WHERE account_role='MASTER')"
+ "FROM account LIMIT 1",
nativeQuery=true)
public List<Integer> getTotalAccountType();
The code executed fine, but the result wasn't what I expected.
Result:
[2]
Expected result: [2,10,30]
Any idea how would I use nested SQL with JPQL? Thank you in advance!
If repository method returns List of Integers it means that query result row contains an Integer value. But you expect to get sequence of Integers in one row.
You can get same result different way:
#Query(value="SELECT COUNT(*) FROM account WHERE account_role=?", nativeQuery=true)
public Integer getTotalAccountType(String role);
and then:
Integer userCount = repository.getTotalAccountType("USER");
Integer adminCount = repository.getTotalAccountType("ADMIN");
Integer masterCount = repository.getTotalAccountType("MASTER");
or if you have mapped entity:
create Pair<K,V> class with constructor Pair(K key, V value) or use it from any external library
repository method based on hql query
#Query(value="select new javafx.util.Pair(a.accountRole, count(a)) from Account a group by a.accountRole")
public List<Pair<String, Integer>> getRoleCountList();
convert repository result to a Map<String, Integer> in service
javafx.util.Pair<String, Integer> result = repository.getRoleCountList();
Map<String, Integer> map = result.stream().collect(Collectors.toMap(r-> r.getKey(), r-> r.getValue()));
Try returning Object[] rather than a List<Integer>. I think returning List<Integer> would indicate multiple rows of an Integer value are being returned, whereas you're getting back one row with multiple Intger columns.
From the resulting Object[] you would pull out the first value (indicating a row). This should be another Object[], which will have your values in the order returned.
You can also remove that last "FROM account LIMIT 1" line, as it has no bearing on the result.
I would recommend casting all of this to an object though. As seen here -
How to return a custom object from a Spring Data JPA GROUP BY query
I have a very strange problem.
I have some repository method that accepts Pageable as parameter. Here it is:
#Query(value = "SELECT product_name FROM product WHERE number = 1",
countQuery = "SELECT COUNT (id) FROM product",
nativeQuery = true)
public List<String> getAllProducts(Pageable pageable);
When I use this method without sort inside of pageable everything is okay. Hibernate uses next query in this situation: SELECT product_name FROM product WHERE number = 1 limit ?.
But when I use sort inside of Pageable I get such a strange query: SELECT product_name FROM product WHERE number = 1, product_name asc limit ?.
Do you have any suggestions why spring puts comma instead of ORDER BY?
org.hibernate
hibernate-core
4.3.8.Final
org.hibernate
hibernate-entitymanager
4.3.8.Final
My pom.xml
My Problem is: How to make a query like this...
SELECT
TABLE_D.*,
TABLE_A.NAME_A
FROM
TABLE_D
INNER JOIN
TABLE_E
ON TABLE_D.ID_TAB_E = TABLE_D.ID_TAB_D
LEFT JOIN
TABLE_C
ON TABLE_C.ID_TAB_C = TABLE_D.ID_TAB_D
INNER JOIN
TABLE_B
ON TABLE_B.ID_TAB_B = TABLE_C.ID_TAB_C
INNER JOIN
TABLE_A
ON TABLE_A.ID_TAB_A = TABLE_B.ID_TAB_B
WHERE
TABLE_A.NAME_A = "XXXX";
And Return the selected the values TABLE_D and TABLE_A in a unique Object List(ex: Object that i create to take all this fields) (I could create 1 filter, whatever...) in the JPA ? Plz Help.
If you need to return a list of selected columns in HQL you can just write your hql query and return a List of Object array, i.e.:
List<Object[]> result = session.createQuery("select a.field1, b.field2 from EntityA a join a.entityB b").list();
then you can iterate and get values, based on their type (i.e. String):
for (Object[] arr : result) {
String col1 = (String)arr[0];
String col2 = (String)arr[1];
}
i have a criteria like
public ArrayList<Student>getStudentsWithPicture(final Student student)
{
final Criteria criteria = session.createCriteria(Student.class).add(and(prepareForSelect()));
criteria.add(Subqueries.gt(1L,getDetached);//the students with a less added picture...
return new ArrayList<Student>(criteria.list());
}
i need the students with a less a picture in the table Pictures but this Database is a legacy one
they store the pictures concatening some fields for the student entity
yes a quite weird
i want something like this
SQL
select
this_.ID as y0_,
this_.C01 as y1_,
this_.C02 as y2_,
this_.C03 as y3_
from
student_table this_
where
(
and this_.C11=true
and 1>=
(
select
count(*)
from
PICTURE_TABLE this_
where
(
this_.C03='concatening'+ this_.ID+ this_.C01+this_.C02+this_.C03//the fields of the student
)
)
)
this is just a understandable example the actual query is a lot worse...
as you can see i want the students with status='true' and they have a less one match on the PICTURE_TABLE but the field C03 from the table is created by concatening the fields of the Student which i have retrieve it as well...
my detached
public DetachedCriteria getWithDetachedMatchStudentWithPictures()
{
final String concatedFields = ...........how i accomplish this??????.................
final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Pictures.class)
.add(equals("c03",concatedFields))
.setProjection(addProjection("id"))
.setResultTransformer(transformer(Pictures.class));
return detachedCriteria;
}
my question is.
can i concate the fields at runtime..?? using Criteria A.P.I
there is some approach?
thanks a lot
Yes, we can contact multiple columns run time in hibernate.
i have concat columns in my beloved query.
Query query = session.createQuery("SELECT DISTINCT f.fileid , f.filename, f.filetype , f.folderpath , max(f.version) from FileBean f GROUP BY concat(folderpath,filename,'.',filetype)");
result = query.list();
i have next tables:
Table table1
table1Id
field1
field2
field3
Table table2
table2Id
table2_field1
table2_field2
table2_field3
table1Id
in this method i get Objects from table1 sorted by some field
public List<table1> getMost() {
DetachedCriteria criteria = (DetachedCriteria) DetachedCriteria.forClass(table1.class);
//criteria.add(Restrictions.conjunction());
criteria.addOrder(Order.desc("field1"));
List<table1> myList = (List<table1>) findByCriteria(criteria,
false, 0, 10);//get first 10 elements by some criteria
return myList;
}
then i need to get Objects from database sorted by some field, but these Objects depend on Objects from table1
public Item getTheBest(Long table1Id) {
DetachedCriteria criteria = (DetachedCriteria) DetachedCriteria
.forClass(Item.class);
DetachedCriteria maxQuery = DetachedCriteria.forClass(Item.class);
maxQuery.add(Restrictions.eq("table1Id", table1Id)).setProjection(
Projections.max("table2_field1"));
criteria.add(Restrictions.and(
Restrictions.eq("table1Id", table1Id),
Property.forName("table2_field1").eq(maxQuery)));
List<Item> result = (List<Item>) findByCriteria(criteria, false);
if (result.iterator().hasNext())
return result.iterator().next();
else
return null;
}
what i want to have is method like this:
public Item getTheBest(List<Long> table1Ids)
thus this method composes these two above methods and makes less calculations.
the idea of the method is to have a Collection of Objects, sorted by one criteria and after sorting by this criteria, we choose items by some field.
so how can i do it in hibernate?
What I understood from above is you have 'A Ordered query result and you want to filter it further".
You can do it in native SQL and use hibernate to convert query result to java objects. Following is an example
SELECT
FROM (SELECT t1.a, t1.b FROM table1 t1 {GROUP BY if needed} ORDER BY t1.a) subTable,
table2 t2
WHERE t1.a = SOMETHING
AND t2.x = SOMETHING