How to get value of some fields in a native query (JPA)?
For example I want to get name and age of customer table:
Query q = em.createNativeQuery("SELECT name,age FROM customer WHERE id=...");
Note: I don't want to map results to entities. I just want to get the value of the field.
Thanks
A native query with multiple select expressions returns an Object[] (or List<Object[]>). From the specification:
3.6.1 Query Interface
...
The elements of the result of a Java
Persistence query whose SELECT clause
consists of more than one select
expression are of type Object[]. If
the SELECT clause consists of only one
select expression, the elements of the
query result are of type Object. When
native SQL queries are used, the SQL
result set mapping (see section
3.6.6), determines how many items (entities, scalar values, etc.) are
returned. If multiple items are
returned, the elements of the query
result are of type Object[]. If only a
single item is returned as a result of
the SQL result set mapping or if a
result class is specified, the
elements of the query result are of
type Object.
So, to get the name and age in your example, you'd have to do something like this:
Query q = em.createNativeQuery("SELECT name,age FROM customer WHERE id = ?1");
q.setParameter(1, customerId);
Object[] result = (Object[])q.getSingleResult();
String name = result[0];
int age = result[1];
References
JPA 1.0 specification
Section 3.6.1 "Query Interface"
Section 3.6.6 "SQL Queries"
Depends on the JPA implementation. Hibernate does it different than castor, for example.
Here's a example how it would work in Hibernate:
Query query = session.createSQLQuery(
"select s.stock_code from stock s where s.stock_code = :stockCode")
.setParameter("stockCode", "7277");
List result = query.list();
I don't think that it is possible to get a plane value such as an integer... but this one should come very close to it.
Related
I am trying to implement a custom text search in lookerstudio (formerly datastudio) dashboard using a custom SQL query as the datasource and a paramater which will be a sentence to search on.
The sentence will be passed to a BQ remote function and the cloud function will return matching results.
So far I have mocked the cloud function to return a string of matching IDs as the BQ remote function expects the result length to match the call length.
'{"replies":["ID1,ID2,ID3"]}'
I have tried the following to get the results back initially:
#standardSQL
WITH query AS(SELECT "test sentence query" AS user_query)
SELECT
S.Description,
SPLIT(`data`.search_function(user_query)) as ID
FROM query
LEFT JOIN `data.record_info` AS S
ON ID = S.ID
The SPLIT IDs are coming out into 1 row ID (when I run the query without the left join). In addition I can't seem to get it unnested and the description column pulled in, I get the error:
Expecting 14552 results but got back 1
Is this method of search in datastudio going to be possible?
Posting this here in case anyone else needs a solution to this problem
WITH Query AS(SELECT "test sentence query" AS user_query)
SELECT
S.Description,
ID
FROM
Query,
UNNEST(SPLIT(`data`.search_function(user_query))) as ID
LEFT JOIN `data.record_info` AS S
ON ID = S.ID
The main difference here is the need for the inclusion of the UNNEST function since SPLIT won't separate the input into multiple rows, even if it appears to do so.
I have a SQL queries with a where clauses that have to exclude rows based on a list of values of some columns, these list may be hard coded (suplied by the users) or constructed from other select query.
Also the hard coded list may be updated by the users, so I need every time to update the list on the query, and that is inconvinient.
I am wondering about the best way to parameter these lists.
Exemple of WHERE clause :
WHERE
Article_Code not in ('PA_003','PA_003','PE_234','FR_980','FA_333','FC_001','TA_999','FC_212','DC_009','FF_333','PR_001')
AND
((Partner_Status != 'Radied') or (Partner_Status = 'Radied' and Partner_Code in ('PR_000453','PR_0004311T','PR_V3345','PR_004D55') ))
AND
(Case_Code not in (select Case_Code from Agreement where DDR = 3))
One though is to build a table of parameter with this structure : (ExclusionCode - Column - ColumnMemberToExclude - ExclusionDescription) :
ExclusionCode is an internal code that I gnerate to identify the reason of exclusion.
Colum is the column to use on the where (ex: Article_Code)
ColumnMemberToExclude is the member to use in the where (ex: PA_003)
ExclusionDescription : functional description (ex: exclude the list of porsche product)
and then construct the where clause as a string from this table.
Is this the best way to do ?
I want to have an HQL query which essentially does this :
select quarter, sum(if(a>1, 1, 0)) as res1, sum(if(b>1, 1, 0)) as res2 from foo group by quarter;
I want a List as my output list with Summary Class ->
Class Summary
{
long res1;
long res2;
int quarter;
}
How can I achieve this aggregation in HQL? What will be the hibernate mappings for the target Object?
I don't want to use SQL kind of query that would return List<Object[]> and then transform it to List<Summary>
Since Summary is not an entity, you don't need a mapping for it, you can create an appropriate constructor and use an HQL constructor expression instead. Aggregate functions and ifs are also possible, though you need to use case syntax instead of if.
So, if Foo is an entity mapped to the table Foo it would look like this:
select new Summary(
f.quarter,
sum(case when f.a > 1 then 1 else 0 end),
sum(case when f.b > 1 then 1 else 0 end)
) from Foo f group by f.quarter
See also:
Chapter 16. HQL: The Hibernate Query Language
It might be possible with a subselect in the mapping. Have a look at More complex association mappings in the hibernate documentation. I've never tried that possibility.
But even the hibernate guys recommend "... but it is more practical to handle these kinds of cases using HQL or a criteria query." That's what I would do: Use the group-by in the HQL statement and work with the List. The extra time for copying this list into a list of suitable objects is negligible compared with the time which the group-by is using in the database. But it seems you don't like this possibility.
A third possibility is to define a view in the database containing your group-by and then create a normal mapping for this view.
I'm having difficulties with translating following SQL syntax into Criteria API:
SELECT AVG(dbo.Member.Points) FROM dbo.Member WHERE dbo.Member.PaidMemberRegDate IS NOT NULL;
I have a Member class with a Points property. I just want to get the average Points of all Members that have the property PaidMemberRegDate set to null.
You should be able to use Projections to take care of this:
Criteria criteria = session.createCriteria(dbo.Member.class)
.setProjection(Projections.avg("Points"))
.add(Restrictions.isNotnUll("PaidMemberRegDate"))
Change the values around to match your class and associations and that should do it.
How can HQL be used to select specific objects that meet a certain criteria?
We've tried the following to generate a list of top ten subscribed RSS feeds (where SubscriptionCount is a derived property):
var topTen = UoW.Session.CreateQuery( #"SELECT distinct rss
FROM RssFeedSubscription rss
group by rss.FeedUrl
order by rss.SubscriptionCount DESC
")
.SetMaxResults(10)
.List<RssFeedSubscription>();
Where the intention is only to select the two unique feed URLs in the database, rather than the ten rows int the database instantiated as objects. The result of the above is:
Column 'RssSubscriptions.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
It's possible just to thin out the results so that we take out the two unique feed URLs after we get the data back from the database, but there must be a way to do this at the DB level using HQL?
EDIT: We realise it's possible to do a Scalar query and then manually pull out values, but is there not a way of simply specifying a match criteria for objects pulled back?
If you change your HQL a bit to look like that:
var topTen = UoW.Session.CreateQuery( #"SELECT distinct rss.FeedUrl
FROM RssFeedSubscription rss
group by rss.FeedUrl
order by rss.SubscriptionCount DESC
")
.SetMaxResults(10)
.List();
the topTen variable will be an object[] with 2 elements in there being the 2 feed URLs.
You can have this returned as strongly typed collection if you use the SetResultTransformer() method of the IQuery interfase.
You need to perform a scalar query. Here is an example from the NHibernate docs:
IEnumerable results = sess.Enumerable(
"select cat.Color, min(cat.Birthdate), count(cat) from Cat cat " +
"group by cat.Color"
);
foreach ( object[] row in results )
{
Color type = (Color) row[0];
DateTime oldest = (DateTime) row[1];
int count = (int) row[2];
.....
}
It's the group by rss.FeedUrl that's causing you the problem. It doesn't look like you need it since you're selecting the entities themselves. Remove that and I think you'll be good.
EDIT - My apologies I didn't notice the part about the "derived property". By that I assume you mean it's not a Hibernate-mapped property and, thus doesn't actually have a column in the table? That would explain the second error message you received in your query. You may need to remove the "order by" clause as well and do your sorting in Java if that's the case.