I have code like this...
Query query = em.createQuery("select CM.salesAreaId, SM.salesAreaDesc, count(CM.salesAreaId), sum(CM.openBal), " +
"sum(CM.netSales) from CustomerMaster CM, SalesAreaMaster SM where CM.salesAreaId=SM.salesAreaCode and CM.companyId=SM.companyId" +
" and CM.companyId=:companyId group by CM.salesAreaId, SM.salesAreaDesc");
query.setParameter("companyId", companyId);
List list = query.getResultList();
From above code how can i get the list values?(list.get() values prints objects)
Try this
Query query = em.createQuery("select CM.salesAreaId, SM.salesAreaDesc, count(CM.salesAreaId), sum(CM.openBal), " +
"sum(CM.netSales) from CustomerMaster CM, SalesAreaMaster SM where CM.salesAreaId=SM.salesAreaCode and CM.companyId=SM.companyId" +
" and CM.companyId=:companyId group by CM.salesAreaId, SM.salesAreaDesc");
query.setParameter("companyId", companyId);
List list = query.getResultList();
for(Object o : list) {
Object[] obj = (Object[])o;
}
And the value of CM.salesAreaId should be in obj[0]
You could use a for loop to iterate through, providing the index each time.
for (int i = 0; i < list.size(); i++)
{
Object x = list.get(i);
...
}
http://docs.oracle.com/javase/6/docs/api/java/util/List.html#get(int)
as JPA is an ORM spec, query result will necessary be a set of Objects. There is a workaround with hibernate if you're using this last as JPA implementation (see How to fetch hibernate query result as associative array of list or hashmap) but your code will be heavily coupled to hibernate then.
If you want to retrieve result as a resultSet (set of primitive values) you should use jdbc directly.
If your problematic is just to print the result in an human readable way you should override toString() method for all your JPA entities.
Related
I use JPA 1.0:
Query query;
query = em.createNamedQuery("getThresholdParameters");
query.setParameter(1, Integer.parseInt(circleId));
List<Object[]> resultList = new ArrayList();
resultList = query.getResultList();
Here I get result as List<Object[]>, thus I have to type convert all the parameters of the row to their respective types which is cumbersome.
In JPA 2.0 there is TypedQuery which return an entity object of type one specifies.
But as I am using JPA 1 I can't use it.
How to get result as Entity object of type I want??
EDIT:
QUERY
#Entity
#Table(name="GMA_THRESHOLD_PARAMETERS")
#NamedQuery(
name = "getThresholdParameters",
query = "select gmaTh.minNumberOc, gmaTh.minDurationOc, gmaTh.maxNumberIc, gmaTh.maxDurationIc, gmaTh.maxNumberCellId,"
+ "gmaTh.distinctBnumberRatio, gmaTh.minPercentDistinctBnumber from GmaThresholdParameter gmaTh "
+ "where gmaTh.id.circleId=?1 AND gmaTh.id.tspId=?2 AND gmaTh.id.flag=?3 "
)
Your query selects many fields. Such a query always returns a list of Object arrays. If you want a list containing instances of your GmaThresholdParameter entity, then the query should be
select gmaTh from GmaThresholdParameter gmaTh
where gmaTh.id.circleId=?1 AND gmaTh.id.tspId=?2 AND gmaTh.id.flag=?3
The code to get the list of entities would then be
List<GmaThresholdParameter> resultList = query.getResultList();
You'll get a type safety warning from the compiler, that you can ignore.
I can't respond to this as a comment so I'll just go ahead and make it an answer.
List<Object[]> resultList = new ArrayList(); // CREATE an empty ArrayList object
resultList = query.getResultList(); // getResultList ALSO returns its own ArrayList object
And since you assign the list that getResultList() returns to the same variable as you used for your own empty ArrayList, your application loses any connection to your own empty ArrayList and Java will collect it as garbage. Essentially you created it for absolutely no purpose.
what JB Nizet posted is enough.
List<GmaThresholdParameter> resultList = query.getResultList();
I have done something similar since I was using JPA 1 at that time:
final Collection<YourType> typedResult = new ArrayList<YourType>
for(final Object result : query.getResultList())
{
typedResult.add((YourType) result);
}
return typedResult;
List<GmaThresholdParamerter> result= query.getResultList();
for( GmaThresholdParamerter res : result)
{
System.out.println("" +res.getMinNumberOc());
System.out.println("" +res.getMinDurationOc());
}
I'm fetching object list from session.createSQLQuery().
I didnt make any pojo classes for it because I don't want it
This object contain 2 variables , I want to fetch those variables who can I
My code
session = sessionfactory.openSession() ;
query = session.createSQLQuery("select id from A_Cleanup") ;
List Ids = query.list() ;
for (Iterator iterator = Ids.iterator(); iterator.hasNext(); iterator.next()){
query = session.createSQLQuery("select distinct rec_category, a_id from a_cdr where a_id in (select id from alerts where al_id = :aid)")
.setParameter("aid", Long.parseLong(Ids.get(0).toString())) ;
java.util.List result = query.list() ;
System.out.println("printing class object" +result.get(0).getClass()) ;
}
session.close() ;
Question:
result.get(0) is a object contain value rec_category and a_id. How can I fetch this variables ?
The result.get(0) returns an Object[] (in this case with 2 elements). So cast it first to Object[], then retrieve each element separately and cast them to their proper types.
Object[] foo = (Object[]) result.get(0);
System.out.println(foo[0] + " and " + foo[1]); // Then cast each one to their real types
I have some very complicated SQL (does some aggregation, some counts based on max value etc) so I want to use SQLQuery rather than Query. I created a very simple Pojo:
public class SqlCount {
private String name;
private Double count;
// getters, setters, constructors etc
Then when I run my SQLQuery, I want hibernate to populate a List for me, so I do this:
Query hQuery = sqlQuery.setResultTransformer(Transformers.aliasToBean(SqlCount.class));
Now I had a problem where depending on what the values are for 'count', Hibernate will variably retrieve it as a Long, Double, BigDecimal or BigInteger. So I use the addScalar function:
sqlQuery.addScalar("count", StandardBasicTypes.DOUBLE);
Now my problem. It seems that if you don't use the addScalar function, Hibernate will populate all of your fields with all of your columns in your SQL result (ie it will try to populate both 'name' and 'count'). However if you use the addScalar function, it only maps the columns that you listed, and all other columns seem to be discarded and the fields are left as null. In this instance, it wouldn't be too bad to just list both "name" and "count", but I have some other scenarios where I need a dozen or so fields - do I really have to list them all?? Is there some way in hibernate to say "map all fields automatically, like you used to, but by the way map this field as a Double"?
Is there some way in hibernate to say "map all fields automatically.
No, check the document here, find 16.1.1. Scalar queries section
The most basic SQL query is to get a list of scalars (values).
sess.createSQLQuery("SELECT * FROM CATS").list();
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
These will return a List of Object arrays (Object[]) with scalar values for each column in the CATS table. Hibernate will use ResultSetMetadata to deduce the actual order and types of the returned scalar values.
To avoid the overhead of using ResultSetMetadata, or simply to be more explicit in what is returned, one can use addScalar():
sess.createSQLQuery("SELECT * FROM CATS")
.addScalar("ID", Hibernate.LONG)
.addScalar("NAME", Hibernate.STRING)
.addScalar("BIRTHDATE", Hibernate.DATE)
i use this solution, I hope it will work with you.
with this solution you can populate what you select from the SQL, and return it as Map, and cast the values directly.
since hibernate 5.2 the method setResultTransformer() is deprecated but its work fine to me and works perfect.
if you hate to write extra code addScalar() for each column from the SQL, you can implement ResultTransformer interface and do the casting as you wish.
ex:
lets say we have this Query:
/*ORACLE SQL*/
SELECT
SEQ AS "code",
CARD_SERIAL AS "cardSerial",
INV_DATE AS "date",
PK.GET_SUM_INV(SEQ) AS "sumSfterDisc"
FROM INVOICE
ORDER BY "code";
note: i use double cote for case-sensitive column alias, check This
after create hibernate session you can create the Query like this:
/*Java*/
List<Map<String, Object>> list = session.createNativeQuery("SELECT\n" +
" SEQ AS \"code\",\n" +
" CARD_SERIAL AS \"cardSerial\",\n" +
" INV_DATE AS \"date\",\n" +
" PK.GET_SUM_INV(SEQ) AS \"sumSfterDisc\"\n" +
"FROM INVOICE\n" +
"ORDER BY \"code\"")
.setResultTransformer(new Trans())
.list();
now the point with Trans Class:
/*Java*/
public class Trans implements ResultTransformer {
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
#Override
public Object transformTuple(Object[] objects, String[] strings) {
Map<String, Object> map = new LinkedHashMap<>();
for (int i = 0; i < strings.length; i++) {
if (objects[i] == null) {
continue;
}
if (objects[i] instanceof BigDecimal) {
map.put(strings[i], ((BigDecimal) objects[i]).longValue());
} else if (objects[i] instanceof Timestamp) {
map.put(strings[i], dateFormat.format(((Timestamp) objects[i])));
} else {
map.put(strings[i], objects[i]);
}
}
return map;
}
#Override
public List transformList(List list) {
return list;
}
}
here you should override the two method transformTuple and transformList, in transformTuple you have two parameters the Object[] objects its the columns values of the row and String[] strings the names of the columns the hibernate Guaranteed the same order of of the columns as you order it in the query.
now the fun begin, for each row returned from the query the method transformTuple will be invoke, so you can build the row as Map or create new object with fields.
I have a resultList which fetches result from a JPQL query that queries multiple tables as described :
Query query = em.createQuery("SELECT protein.gid,protein.uniProtAccession,protein.name,protein.ECNumber,ttdtarget.uniProtID,ttdtarget.gid FROM Protein protein,TtdTarget ttdtarget WHERE protein.uniProtAccession = ttdtarget.uniProtID");
List resultList = query.getResultList();
Note: I am restricting the size of resultset to 5 right now, just for debugging. I want to get the values returned inside each object from the resultList, which basically is an array of objects.
So far I have tried iterating upto the objects but can't access the inner values.
for (int i = 0; i < resultList.size(); i++)
{
System.out.println("->"+resultList.get(i));
}
Output:
->[Ljava.lang.Object;#141ab9e
->[Ljava.lang.Object;#6a15ca
->[Ljava.lang.Object;#bcb654
->[Ljava.lang.Object;#1664b54
->[Ljava.lang.Object;#db953c
And here is the variable's output from debug:
So my question is how to access those values inside the object.
The result is List<Object[]>, so cast to that. So a list, where each element is an array of values. You must then cast each value to its type (which you know beforehand).
If you simply want to iterate and print:
List<Object[]> resultList = (List<Object[]>) query.getResultList();
for (Object[] array : resultList) {
for (Object field : array) {
System.out.println("->"+field);
}
}
Alternatively, you can create a new class which has these exact fields, make its constructor accept all of the values, and use it in the query: SELECT new Foo(.....) FROM... There you can use the generic alternative of em.createQuery(..) that returns TypedQuery
You don't have a List of Objects, it is a List of Objectarrys
List<Object[]> resultList = (List<Object[])resultList;
for (int i = 0; i < resultList.size(); i++)
{
System.out.print("protein.gid ->"+resultList.get(i)[0]);
System.out.println("protein.uniProtAccession ->"+resultList.get(i)[1]);
}
List<Object[]> resultList = query.getResultList();
for (Object[] objects : resultList)
{
for (Object object : objects)
{
System.out.println(object)
}
}
Your result form the query is array of objects.
List resultList = query.getResultList();
for(Object result : resultList) {
Object[] results = (Object[]) result;
for(Object res : results) {
System.out.println(res);
}
}
Or you can go with Bozho solution and create new direct from query.
You can create a new class with the exact fields you need and use a TypedQuery
TypedQuery<CustomClass> query = em.createQuery("" /* Query String */, CustomClass.class);
List<CustomClass> resultList = query.getResultList();
foreach (CustomClass result : resultList){
// Need to override method toString() in CustomClass
System.out.println("->" + result);
}
I'm tempted to suggest nesting a for loop:
for (int i = 0; i < resultList.size(); i++)
{
for(int j = 0; j < resutList.get(i).size(); j++){
System.out.println("->"+resultList.get(i).get(j));
}
}
I am new to JPA. So my question should be so simple to some.
Below is the Simple Query in SQL which i would like to convert to JPA. I already have an entity class called TimeEnt.
SELECT
SUM(TimeEntryActualHours) as UnBilledHrs,
SUM (TimeEntryAmount) as UnbilledAmount
FROM TimeEnt WHERE MatterID = 200
The JPA Query Language does support aggregates functions in the SELECT clause like AVG, COUNT, MAX, MIN, SUM and does support multiple select_expressions in the SELECT clause, in which case the result is a List of Object array (Object[]). From the JPA specification:
4.8.1 Result Type of the SELECT Clause
...
The result type of the SELECT
clause is defined by the the result
types of the select_expressions
contained in it. When multiple
select_expressions are used in the
SELECT clause, the result of the query
is of type Object[], and the
elements in this result correspond in
order to the order of their
specification in the SELECT clause
and in type to the result types of
each of the select_expressions.
In other words, the kind of query you mentioned in a comment (and since you didn't provide your entity, I'll base my answer on your example) is supported, no problem. Here is a code sample:
String qlString = "SELECT AVG(x.price), SUM(x.stocks) FROM Magazine x WHERE ...";
Query q = em.createQuery(qlString);
Object[] results = (Object[]) q.getSingleResult();
for (Object object : results) {
System.out.println(object);
}
References
JPA 1.0 Specification
4.8.1 Result Type of the SELECT Clause
4.8.4 Aggregate Functions in the SELECT Clause
Lets think we have entity called Product:
final Query sumQuery = entityManager
.createQuery("SELECT SUM(p.price), SUM(p.sale) FROM Product p WHERE p.item=:ITEM AND ....");
sumQuery.setParameter("ITEM","t1");
final Object result= sumQuery.getSingleResult(); // Return an array Object with 2 elements, 1st is sum(price) and 2nd is sum(sale).
//If you have multiple rows;
final Query sumQuery = entityManager
.createQuery("SELECT SUM(p.price), SUM(p.sale) FROM Product p WHERE p.item in (" + itemlist
+ ") AND ....");
// Return a list of arrays, where each array correspond to 1 item (row) in resultset.
final List<IEniqDBEntity> sumEntityList = sumQuery.getResultList();
Take a look at the EJB Query Language specification.
The idiom is very similiar to standard SQL
EntityManager em = ...
Query q = em.createQuery ("SELECT AVG(x.price) FROM Magazine x");
Number result = (Number) q.getSingleResult ();
Regards,