How to get data from raw query in spring boot? - java

I have a query:
Query q = em.createNativeQuery("select DISTINCT id, rating, random() as ordering FROM table\n" +
" WHERE id not in (1,2) ORDER BY ordering LIMIT 10");
List data = q.getResultList();
Every element of this list is array like object:
I want to retrieve that "8" and "16" and compose a comma separated string (to use it in my query in "not in" section in future):
for (Object x : data) {
System.out.println(Arrays.asList(x).get(0));
}
But it produces strings:
[Ljava.lang.Object;#ee93cd3
[Ljava.lang.Object;#62f3c3e1
I don't know how to get that IDs ("8" and "16")

1.I think this is what you are looking for...
Convert JPA query.getResultList() to MY Objects.
or
List<Object[]> rows = q.getResultList(); for (Object[] row : rows) { System.out.println(row[0]); }

in this line
List<Object[]> data = q.getResultList();
data is list of Object of form
[ [1,233, 0.000333], [1,233, 0.000333] ]
for (Object[] x : data) {
// x is [1,233, 0.000333]
System.out.println(x[0]);
}

If I understood it correctly, you are looking for comma separated string of ID's.
If so, then follow these steps might help you to solve the issue.
Create a constructor in table which has only one parameter ID. (If you want you can add more parameters as well but make sure the value which you want it must be in constructor as well as in query.)
Write sql query and execute it.
It returns result and gather it in List which contains the object of the table.
Get the string
dataList.stream().map(obj -> obj.getId()).collect(Collectors.joining(", "))
This will give you the comma separated string.

Related

How to avoid this error on Spring Boot: (query did not return a unique result: 4)

I am try to get some random data from the MySql data base,
in order to get that data I use the following query
#Query(nativeQuery = true,value = "select question from test_questions order by RAND() limit 4")
and I put that query in Jpa Repository interface and I made this custom Method
public String getRandItems();
but when I try to fetch data from postman it gives me this error
query did not return a unique result: 4
Note that it works for me when I use select * instead of select question but I do not want the whole data I just want the question column.
You are limitting the result to 4 rows, so you should return a List of Strings instead of a simple String as result:
public List<String> getRandItems();
You are limiting the result to 4 rows, so you should return a List of Strings instead of a simple String as result:
public List<String> getRandItems();
or you can limit the result by 1 to get only one string:
#Query(nativeQuery = true,value = "select question from test_questions order by RAND() limit 1")
Look at the error it says that it did not return unique result because it is returning more the one result which does not matching with the method return type.
Yes as it is returning more than one result so it can store it in a single string you can change your method signature from
public String getRandItems();
To :
public List<String> getRandItems();
So it accepts all the results

Hibernate result list cast to get rows

Hello I had problem with iterate Hibernate ResultList
I had followed query that I got from external class:
queryContent = "select distinct c.identity, c.number, c.status, ctr.name, aab.paymentConditions.currency from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
And I must sum whole aab.paymentConditions.currency, check numbers of statutes and names.
I want to do this by iterate list of results:
Query q = session.createQuery(queryContent);
List result = q.list();
Long wholeCurrency, numberOfStatutes;
for(Object res : result){
//wholeCurrency += res.getColumnName?
}
My question is how to cast res Object to have possibility to get concrete column values? I had read about create map inside hibernate query but I don't know it is good practice to modyfied query string by adding
"new map(" prefix and then ")"
before from sql statement
Solution:
After All I decided to use map in my query. I modified my external query by adding hibernate map statement by replacing select by 'select new map(' and from by ') from'.
Additional thing is to add 'as' statement with name of key because without them column keys are integer.
So after all my query looks like follow:
"select new map( distinct c.identity, c.number, c.status as status, ctr.name as name, aab.paymentConditions.currency as currency ) from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
That was the most siutable solution for me, I tried with 'NEW com.example.MyClass' as Kostja suggested but in my case I didn't have control for incoming query so I can not rely on pernament constructor.
new List( select...
Is also interest but it also didn't tell me on with position I have my field that give me information.
If I understand correctly, you want to have a typed representation of your result without it being an entity itself. For this, you can use constructor queries:
"SELECT NEW com.example.MyClass( e.name, e.data) FROM Entity e"
MyClass has to have a matching constructor. Full qualification (com.example) is not mandatory AFAIK.
If you are using this query often, creating a view in the DB may be a good idea. You can map a view to an entity just as if it were a regular table, but please note that you cannot store changes to you data over a mapped view.
EDIT: Turns out, mapping to an unspecified Map is alright with Hibernate:
select new map( mother as mother, offspr as offspr, mate as mate )
As per http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch11.html#ql-select-clause
you can use
queryContent = "select new list(distinct c.identity, c.number, c.status, ctr.name, aab.paymentConditions.currency) from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
And you get List<List> as result.

Get single ScrollableResults row

I am trying to extract count(*) matching certain predicates. Every time I use createSQLQuery, I find myself having to write the code along the lines of,
// skipped code
Query q = session.createSQLQuery("select count(*) from A where id=1");
Scrollable results = q.scroll();
while ( results.next() )
{
Object[] row = Object[] results.get();
// Assign it
String str = row[0];
//set and persist
}
I have many such queries unioned over a single transaction. How do I get single result here? Am I missing something?
You can use this method instead:
Object[] row = (Object[]) query.uniqueResult();
If the query returns more than one result, this method will throw an exception
EDIT:
On top of that, you could use a ResultTransformer to convert the Object[] into an Integer. This would remove the need to get the result array and then extract it's first entry. See this example for more info

How to query for a List<String> in JdbcTemplate?

I'm using Spring's JdbcTemplate and running a query like this:
SELECT COLNAME FROM TABLEA GROUP BY COLNAME
There are no named parameters being passed, however, column name, COLNAME, will be passed by the user.
Questions
Is there a way to have placeholders, like ? for column names? For example SELECT ? FROM TABLEA GROUP BY ?
If I want to simply run the above query and get a List<String> what is the best way?
Currently I'm doing:
List<Map<String, Object>> data = getJdbcTemplate().queryForList(query);
for (Map m : data) {
System.out.println(m.get("COLNAME"));
}
To populate a List of String, you need not use custom row mapper. Implement it using queryForList.
List<String>data=jdbcTemplate.queryForList(query,String.class)
Use following code
List data = getJdbcTemplate().queryForList(query,String.class)
Is there a way to have placeholders, like ? for column names? For example SELECT ? FROM TABLEA GROUP BY ?
Use dynamic query as below:
String queryString = "SELECT "+ colName+ " FROM TABLEA GROUP BY "+ colName;
If I want to simply run the above query and get a List what is the best way?
List<String> data = getJdbcTemplate().query(query, new RowMapper<String>(){
public String mapRow(ResultSet rs, int rowNum)
throws SQLException {
return rs.getString(1);
}
});
EDIT: To Stop SQL Injection, check for non word characters in the colName as :
Pattern pattern = Pattern.compile("\\W");
if(pattern.matcher(str).find()){
//throw exception as invalid column name
}
You can't use placeholders for column names, table names, data type names, or basically anything that isn't data.

How to send send an array of objects to a NamedQuery that needs the "id" of all the objects.

I am building a report from information received from a muti-select form element in a jsp page.
In my repository class I am getting an array of objects from that element. I need to call the getId function for each one of these objects and send those ids to the NamedQuery.
Here is a code example to help explain. I know how to handle a single object but with an array of objects I get lost at the .setParameter(1, employees[].getId()) part.
public List<RequestByRequester> getFormInformation(
Employee[] employees)
throws NoDataFoundException {
List<RequestByRequester> resultList = getEm().createNamedQuery(
"requestByRequestor.getRequestsByRequesters", RequestByRequester.class)
.setParameter(1, employees[].getId())
.getResultList();
return resultList;
}
By request the query:
SELECT EMP.EMPL_FIRST_NAME || ' ' || EMP.EMPL_LAST_NAME REQUESTER,
R.RQST_ID RQST_ID,
R.TITLE TITLE,
R.DESCRIPTION DESCR,
DECODE(R.RESOLUTION_DATE, NULL, 'Open', 'Closed') STAT
FROM TARTS.REQUESTS R, SYS_EMPLOYEES EMP
WHERE R.EMPL_ID_REQUESTED_BY = EMP.EMPL_ID
AND EMP.EMPL_ID IN (?)
ORDER BY 1, 5 DESC, 2
I tried calling Madame Mystique to get help with finding out what your query actually was, but no luck, so I'm just going to go for it...
Your named query should look something like this:
select x
from MyClass x
where x.children.id in (:ids)
then get your ids into a list
List<Integer> ids = new ArrayList<Integer>();
ids.add(someid); // etc
then use this to specify it in your query
.setParameter("ids", ids)

Categories

Resources