extract Object parameters to POJO - java

How is it possible to get the [0], ..., [4] parameter's values of the Object below ?
The Object you see below is a result from EntityManager.createNativeQuery().
I would like to use the values to create a POJO. I know I could use EntityManager.createNativeQuery("SQL Query", MyPOJO.class), but it returns POJO only with ID, all other variables are null?! and I am interested in how to get object's parameters.
It's not possible to cast returned object to MyPOJO, because MyPOJO is a JPA Entity with references to another JPA Entities, and the returned object contains only IDs of another JPA Entities.
Thank you!

I solved it the following way:
Let nativeQuery to return me result as a List of Object[] and access the Object's values through index.
Here is my solution:
List<Object[]> executeObjects = null;
Query query = mgr.createNativeQuery("SQL Query");
executeObjects = (List<Object[]>) query.getResultList();
for (Object[] object : executeObjects) {
Long id = new Long((Integer) object[0]);
Long id2 = new Long((Integer) object[1]);
String desc = (String) object[2];
...
...
}

Related

Mapping projection form hibernate HQL query into object

I am returning only a few columns from a table in DB:
List<MyClass> l = (List<MyClass>) session.createQuery("Select p.one, p.two FROM MyClass p WHERE p.id IN :id")
.setParameter("userId", id)
.list();
However, the query returns List of arrays, e.g
l.get(0) // [0] is object representing p.one in query, [1] p.two
Is there a hibernate some effective way how to map it to MyClass object? So the query would actually return list of MyClass objects where selected properties would have values, others would be set to null?
I have read about new MyClass(arg1,arg2) way in the query with construtor, however i have also read it is ineffective.
Thanks for help!
You can use try catch block and use query.getSingleResult() to return Object.
Query query = em.createNativeQuery("FROM TipoUsuario WHERE NAME = :name;", TipoUsuario.class)
.setParameter("name", name);
TipoUsuario tipoUsuario = null;
try
{
tipoUsuario = (TipoUsuario) query.getSingleResult();
}
catch ( Exception e )
{
return null;
}
createNativeQuery is just a sample. You can use createNamedQuery instead and put HQL in Entity with annotation #NamedQueries.
If you want to create MyClass you just need to use the fully-qualified name of the class in your query, e.g.
SELECT NEW my.pack.MyClass(p.one, p.two) FROM MyClass p WHERE p.id IN :id
I haven't heard of this being ineffective, and I can't image why it would be. It's just calling the constructor on the result instead of returning it as an array or object. Overall, it's probably a very good way of fetching, since you only select the fields that you need.
This and other options are also explained in more detail here.

Hibernate SQLQuery list method returns Object instead of object array

I have this strange behavior with Hibernate SQLQuery.list() method.
Following is the description of the issue:
I have a sql select query which retrieves only single column(group) from the database (i.e., select group from peopleGroup where groupid = 10)
And i'm recieving the result of the above list in List of Object array
i.e,
SQLQuery hQuery = session.createSQLQuery("select group from peopleGroup where groupid = 10");
List<Object[]> result = (List<Object[]>)hQuery.list();
Ideally, the result should contain a list of object arrays but when I inspect, 0'th index of the result contains String object instead of an Object array.
However if I use more than one column let's say 2 columns in the select clause of the query I was able to see that 0'th index of the result as Object array i.e., Object[2]={"group","groupid"};
How do I get the Object array even if I have only one column mentioned in the select clause of the query?
Docs states:
List list()
Return the query results as a List. If the query contains multiple
results per row, the results are returned in an instance of Object[].
Convert it by yourself, like so.
List<Object[]> l = new ArrayList<>();
for(Object o : query.list()) {
Object[] arr = {o};
l.add(arr);
}
you can create a object mapper like below code
public class QueryMapper {
private String group;
//setter and getter
}
And you have to change your code like below
SQLQuery hQuery = session.createSQLQuery("select group from peopleGroup where groupid = 10");
List<Object[]> result = (List<Object[]>)hQuery.list();
List<QueryMapper> list = new ArrayList<QueryMapper>();
for(Object[] object: result){
QueryMapper queryMapper = new QueryMapper();
if(object[0]!=null){
queryMapper.setGroup((String)object[2]);
}
list.add(queryMapper);
}
All i wanted is to fix the ClassCastException which was caught during the assignment of result.get(0) to the container i.e., container = result.get(0);
Since the value returned by mentioned list() method contains object in case of single column in the select clause of the query and i won't be allowed to cast from certain object to Object[](Object array).
Instead i have tried a work around like below
Already existing code
SQLQuery hQuery = session.createSQLQuery("select group from peopleGroup where groupid = 10");
List<Object[]> result = (List<Object[]>)hQuery.list();
Object[] container = result.get(0);
now i have put condition like below to decide how to assign value to the Object[]
SQLQuery hQuery = session.createSQLQuery("select group from peopleGroup where groupid = 10");
List<Object[]> result = (List<Object[]>)hQuery.list();
Object[] container = null;
if(result.get(0) instanceof Object[])
container = result.get(0);
else {
container = new Object[1];
container[0] = result.get(0);
}
The above solution seems working in my case !

JPA query.getResultList()?

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

What type of list does list() return?

The following query gets the username from the User entity.
String hql = "SELECT userName FROM User WHERE email= :user_email";
Query query = session.createQuery(hql);
query.setParameter("user_email", userSearched );
What type does 'query.list()' return ?
Will it return List?
Actually it will depends upon what type of query that you have used
As i know it will return Two types of List
List<bean>
Contains the whole data records of a table, when you use like createQuery('from table').list() returns this list, because you retrieve all column records from table.
Object[]
When you specify a particluar column name or names like createQuery('select column1,column2 from table').list() , it will return object[], here every column will be retrieved as object[0],object[1],...
Your createQuery(hql).list() will return List and its not typed. From Java Doc
Return the query results as a List. If the query contains multiple results pre row, the results are returned in an instance of Object[].
You specifiy fields in your query.
The query will result a list of Object[].
You can use a Mapper to map these to an object or reference them by index.
createQuery will return object of type List interface i.e. only List. In your case since you know that it will be list of User object to can explicitly cast to List
No. It will return List<Object>
From docs Query#list
public List list()
throws HibernateException
Return the query results as a List. If the query contains multiple results pre row, the results are returned in an instance of Object[].
So, below code will return Object list.
String hql = "SELECT userName FROM User WHERE email='" + userSearched + "'";
List<Object> usersList = sess.createQuery(hql).list();
You can type cast to create ArrayList<User>
String hql = "FROM User WHERE email='" + userSearched + "'"; //changed the query
ArrayList<User> usersList = (ArrayList<User>) sess.createQuery(hql).list();
Not related
I would recommend use Query#setParameter to set the parameter.
String hql = "FROM User WHERE email = :userSearched";
ArrayList<User> usersList = (ArrayList<User>) sess.createQuery(hql).setParameter("userSearched",userSearched).list();

JPA Query.getResultList() - use in a generic way

I'm creating a complex query with multiple tables and need to list the result. Usually, I'm using the EntityManager and map the result to the JPA-Representation:
UserEntity user = em.find(UserEntity.class, "5");
Then I can access all values as the user UserEntity class defines it. But how can I access the field-values returned from a native, multiple-table query? What I get is a List of Objects. That's fine so far, but what "is" that Object? Array? Map? Collection? ...
//simpleExample
Query query = em.createNativeQuery("SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id");
List list = query.getResultList();
//do sth. with the list, for example access "something" for every result row.
I guess the answer is quite simple, but most examples out there just show the usage when directly casting to a targetClass.
PS: In the example I could use the class-mappings of course. But in my case someTable is not managed by JPA, and therefore I don't have the entity nor do I have a class-representation of it, and since I'm joining like 20 tables, I don't want to create all the classes just to access the values.
General rule is the following:
If select contains single expression and it's an entity, then result is that entity
If select contains single expression and it's a primitive, then result is that primitive
If select contains multiple expressions, then result is Object[] containing the corresponding primitives/entities
So, in your case list is a List<Object[]>.
Since JPA 2.0 a TypedQuery can be used:
TypedQuery<SimpleEntity> q =
em.createQuery("select t from SimpleEntity t", SimpleEntity.class);
List<SimpleEntity> listOfSimpleEntities = q.getResultList();
for (SimpleEntity entity : listOfSimpleEntities) {
// do something useful with entity;
}
If you need a more convenient way to access the results, it's possible to transform the result of an arbitrarily complex SQL query to a Java class with minimal hassle:
Query query = em.createNativeQuery("select 42 as age, 'Bob' as name from dual",
MyTest.class);
MyTest myTest = (MyTest) query.getResultList().get(0);
assertEquals("Bob", myTest.name);
The class needs to be declared an #Entity, which means you must ensure it has an unique #Id.
#Entity
class MyTest {
#Id String name;
int age;
}
The above query returns the list of Object[]. So if you want to get the u.name and s.something from the list then you need to iterate and cast that values for the corresponding classes.
I had the same problem and a simple solution that I found was:
List<Object[]> results = query.getResultList();
for (Object[] result: results) {
SomeClass something = (SomeClass)result[1];
something.doSomething;
}
I know this is defenitly not the most elegant solution nor is it best practice but it works, at least for me.
Here is the sample on what worked for me. I think that put method is needed in entity class to map sql columns to java class attributes.
//simpleExample
Query query = em.createNativeQuery(
"SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id",
NameSomething.class);
List list = (List<NameSomething.class>) query.getResultList();
Entity class:
#Entity
public class NameSomething {
#Id
private String name;
private String something;
// getters/setters
/**
* Generic put method to map JPA native Query to this object.
*
* #param column
* #param value
*/
public void put(Object column, Object value) {
if (((String) column).equals("name")) {
setName(String) value);
} else if (((String) column).equals("something")) {
setSomething((String) value);
}
}
}
What if you create a bean with all required properties and cast the result using Java 8+ streams?
Like this:
public class Something {
private String name;
private String something;
// getters and setters
}
And then:
import javax.persistence.Query;
...
Query query = em.createNativeQuery("SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id", Something.class);
List<?> list = query.getResultList();
return list
.stream()
.map(item -> item instanceof Something ? (Something) item : null)
.collect(Collectors.toList());
That way, you don't need to return List<Object[]> nor hide the warning with #SuppressWarnings("unchecked")
Ps.:
1 - I know that this post is very old. But... I'm here in 2021, so others will be coming here too =)
2 - This is wrong or bad practice? Let me know :D
You can also update your hibernate to a version greater than 5.4.30.final

Categories