How to iterate inside an array of object containing multiple fields? - java

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));
}
}

Related

Convert ArrayList to List<GenericModel> gives ClassCastException

I am converting stored procedure to complete JPA query. One of the SP query is as below which i am converting to entity class. I am converting this to a bean defined as Generic model which results in classcastexception.
SP query whose result set rs4 in java class is as follows:
rs4 Query: select command_value as descr from SCAN_COMMAND_NAME
where command_name = 'AAA' ORDER BY SEQ;
Here the result set rs4 is converted to GenericModel:
ResultSet rs4 = (ResultSet) cs.getObject(cnt++);
List commandRotateLi = new BeanProcessor().toBeanList(rs4,GenericModel.class);
session.setAttribute("coRotate", commandRotateLi);
///...
..///
ArrayList coRotate = (ArrayList) session.getAttribute("coRotate");
for(int x = 0; x < coRotate.size(); x++){
gm = (GenericModel) coRotate.get(x);
///
}
This above code works fine. Below is JPA converted code.
List<ScanCommandName> scanCommandList = new ArrayList<ScanCommandName>();
query = em.createNamedQuery("ScanCommandName.findByCommandName", ScanCommandName.class);
query.setParameter("commandName", Constants.IMAGE_MAGICK_ROTATE);
scanCommandList = query.getResultList();
scanCommandList.toString() gives me 5 ScanCommandName objects. I have to convert this List to List and loop through as above one but struck at class cast exception in the for loop.
ArrayList list = new ArrayList();
List<GenericModel> coRotate = null;
for(int y=0; y<scanCommandList.size(); y++){
ScanCommandName s = scanCommandList.get(y);
list.add(s.getCommandValue());
}
coRotate = (List<GenericModel>) (List) list;
I am now looping through the List coRotate but getting classcast at the 1st line in for loop.
for(int x = 0; x < coRotate.size(); x++){
gm = (GenericModel) coRotate.get(x);
///
}
java.lang.ClassCastException: java.lang.String cannot be cast to com.GenericModel
Any suggestions highly appreciated. thank you.
This is essentially what you are doing:
ArrayList list = new ArrayList();
List<SomeClass> slist;
list.add("String"); // <-- I'm guessing here based on exception
slist = (List<SomeClass>) list;
for (SomeClass s : slist) { // class cast exception
System.out.println(s);
}
class SomeClass {
}
Had you done this:
ArrayList<String> list = new ArrayList<>();
You could not have done this
slist = (List<SomeClass>) list;
And the error would have been caught at compile time.
Without knowing the details of your class structure, I suspect that to do what you want, coRotate needs to hold instances of GenericModel and
your ArrayList needs to be declared as ArrayList<GenericModel> = new ArrayList<>()

Can't iterate over objects in a Java for...loop

I can't add to my list this query:
// This query always return List<Object[]>
Query buscarRad = AreaPrincipal.em.createNamedQuery("Rad.buscarPorCuil");
buscarRad.setParameter("cuil", cuil);
List<Object[]> listaRad = buscarRad.getResultList();
int i = 0;
for (Object[] filaRad : listaRad) {
// if (filaRad[i].equals(null)) {
if (filaRad[i] != null) {
lvRad.getItems().add(filaRad[i].toString());
}
i++;
}
This is my vector listaRad:
I need all values not null
...but my objects list break at first value and finalize. What's wrong?
You need to use nested loops to iterate over all rows, and then to iterate over all columns within each row. Try this:
for (Object[] filaRad : listaRad) { //for DB rows
for (int i = 0; i < filaRad.length; i++) { //for DB columns within a row
if (filaRad[i] != null) {
lvRad.getItems().add(filaRad[i].toString());
}
}
}
Ideally you should put each column's value in an object's field rather than looping and converting them to toString(). Something like this:
List<MyDbRow> rows = new ArrayList<>();
for (Object[] filaRad : listaRad) {
MyDbRow row = new MyDbRow();
row.setId(fileRad[0]); //may require casting
row.setName(fileRad[1]);
rows.add(row);
}
See if this works for you. First you can put all elements at one level in an Object array list. After that you can loop through that list and check for null elements.
// This query always return List<Object[]>
Query buscarRad = AreaPrincipal.em.createNamedQuery("Rad.buscarPorCuil");
buscarRad.setParameter("cuil", cuil);
List<Object[]> listaRad = buscarRad.getResultList();
List<Object> finalList = new ArrayList<>();
int i = 0;
for (Object[] filaRad : listaRad) {
finalList.add(Arrays.asList(filaRad));
}
for(Object o : finalList){
if (o != null) {
lvRad.getItems().add(o.toString());
}
}
In java 8 you can do like this assuming that lvRad.getItems() is a list
itself
lvRad.getItems().addAll(finalList.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList()));

Filter List<Object[]> to retain consistent values

First, I had a list with several arrays of type Object, e.g.:
Object[] arr1 = new Object[] {"FIM4R1500030", BigInteger.valueOf(5272456l), "A10328E00074531842"};
Object[] arr2 = new Object[] {"FIM4R1500031", BigInteger.valueOf(886445384123l), "A10328E00074531842"};
final List<Object[]> arrs = Arrays.asList(arr1, arr2);
Then, I wrote a logic that filters them to retain the consistent values and fills in null for the inconsistent ones. The result looked something like this:
List[
Object[][null,null,"A10328E00074531842"],
Object[][null,null,"A10328E00074531842"]
]
Now, my problem is that the logic for this turned out rather convoluted and difficult to read and I am not sure whether I can live with it. Also, I don't really want to start writing a fully-blown utility class, since the functionality seems small for this. Here is my code:
final Predicate<Integer> isConsistant = index -> {
for (Object[] arr : arrs) {
if (!arr[index].equals(arrs.get(0)[index])) {
return false;
}
}
return true;
};
List<Object[]> filtered = arrs.stream().map(arr -> {
Object[] returnList = new Object[arrs.get(0).length];
for (int i = 0; i < arrs.get(0).length; i++) {
if (isConsistant.test(i)) {
returnList[i] = arrs.get(0)[i];
} else {
returnList[i] = null;
}
}
return returnList;
})
.collect(toList());
My question is, how to make this simpler!
Why do you want a List<Object[]> as the result of your filter? If I understood your problem well, all the Object[] inside that list will look the same. So the code could just be:
Object[] filtered = IntStream.range(0, arrs.get(0).length)
.mapToObj(i -> arrs.stream().allMatch(arr -> arr[i] != null && arr[i].equals(arrs.get(0)[i])) ? arrs.get(0)[i] : null)
.toArray();
The problem with this code is not that it's too complex, but that it is unnecessarily slow: for each pair of (row, column) of arrs you walk the entire array again, trying to determine if all values in the column are equal to each other. Essentially, you are running isConsistant on the same column N times - once for each row, even though the predicate always returns the same value. This may be very significant when the number of rows is high.
The process always ends up with N identical rows, so you might as well construct that row once, and make N copies of it:
Object[] row = new Object[arrs.get(0).length];
for (int i = 0 ; i != arrs.get(0).length ; i++) {
if (isConsistant.test(i)) {
row[i] = arrs.get(0)[i];
}
}
// Now we make N copies of that row:
List<Object[]> filtered = new ArrayList<Object[]>();
for (int i = 0 ; i != arrs.length() ; i++) {
filtered.add((Object[])row.clone());
}
If you are not planning on modifying elements of filtered, you may skip the clone part, and insert the same object N times.

Get values from list object

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.

java: converting DynaBean (apache-commons-beanutils) to List

I use apache-commons-beanutils DynaBean class in order to fetch rows from a database and to handle them outside of the mysql function.
is there a way to convert a DynaBean to a List without iterating through each row and manually creating the list ?
thanks!
so far I didn't get any answers so I wrote the function that iterates through the rows and creates an ArrayList of HashMap type (String, Object).
public ArrayList<HashMap<String,Object>> convertDynaBeanListToArrayList(List<DynaBean> theList) {
ArrayList<HashMap<String,Object>> result = new ArrayList<HashMap<String,Object>>();
DynaProperty[] dynaProperties = null;
for (Integer i=0;i<theList.size();i++) {
DynaBean row = theList.get(i);
HashMap<String,Object> resultRow=new HashMap<String,Object>();
// each raw got the same column names, no need to fetch this for every line
if (dynaProperties == null) {
dynaProperties = row.getDynaClass().getDynaProperties();
}
for (Integer j=0;j<dynaProperties.length;j++) {
String columnName=dynaProperties[j].getName();
resultRow.put(columnName, row.get(columnName));
}
result.add(resultRow);
}
return result;
}

Categories

Resources