How to map native query to one model class? - java

Hi I´m using Eclipselink and I did a native query to select some fields of 2 tables. I mapped my table Logins in a model class. I would not like to map my table "B" because I need only 2 fields of this table on my sql result.. can I map this 2 fields in my Logins table to my sql result ?
My sql is this:
select l.login_id, s.lugarcerto,s.vrum, l.username, l.first_name, l.last_name, l.phone, l.fax_number, l.address, l.zip,
l.address2 as 'birth_date', l.city as 'cpf_cnpj'
from Logins l
join (select se.login_id, lugarcerto = min(case when se.service = 'IM' then '1' end), vrum = min(case when se.service = 'VE' then '1' end)
from (select distinct ad.login_id, substring(ap.Rate_code,(CHARINDEX('-', ap.Rate_code)+1),2) as 'service'
from Ad_Data.dbo.ad ad
join Ad_Data.dbo.ad_pub ap on (ad.ad_id = ap.ad_id)
where ap.ad_type =1) se
group by se.login_id) s on (s.login_id = l.login_id)
I did map Logins table and I want to map s.lugarcerto and s.vrum to my SQL query result.
There´s anyway to just add it to my Logins model ?

Not without having mappings for the attributes you want those values put into, and not without causing problems with them being cached in the entity.
Why not just return the values beside the entity, much like you would with a JPQL query such as: "Select l, subquery1, subquery2 from Logins l" ie:
Query q = em.createNativeQuery(yourQueryString, "resultMappingName");
And in the entity, include the annotation:
#SqlResultSetMapping(name="resultMappingName",
entities={#EntityResult(entityClass=com.acme.Logins.class, )},
columns={#ColumnResult(name="LUGARCERTO"), #ColumnResult(name="VRUM")}
)
Best Regards,
Chris

Related

How to select distinct table from joined tables with Hibernate Criteria API?

I'm trying to implement a query like this:
SELECT DISTINCT C.* FROM A
join B on A.some_id = B.some_id
join C on B.some_id = C.some_id;
With Hibernate Criteria API.
I need to have distinct results for whole C table, not just for some column(s) of it.
I tried to do like that:
Criteria criteria = createCriteria(C.class, "ct")
.createCriteria("B", "bt")
.createCriteria("A", "at")
.//Some restrictions which are applied to all tables
And like that:
Criteria criteria = createCriteria(A.class, "at")
.createCriteria("B", "bt")
.createCriteria("C", "ct")
.//Some restrictions which are applied to all tables
(I don't see a difference though).
Tried to ad ResultTransformer:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
Tried to put all colums into ProjectionsList and then:
criteria.setProjection(Projections.distinct(projectionList));
But that projection only adds "distinct" keyword to first column in list but not to whole table.
What I want to achieve - is something like that:
criteria.setProjection(Projections.distinct("C.*"));
but I only can add a column here, can't use wildcards like in query.
Any help is greatly appreciated.
You should select columns from table 'C' not from table 'A' like below.
SELECT distinct (*) FROM C
it can be written in hibernate criteria as follows:
Criteria criteria = session.createCriteria(C.class);
criteria = criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
ResultTransformer rt = new DistinctRootEntityResultTransformer();
List list = rt.transformList(criteria.list());

How can I correctly implement an Hibernate SQL query starting from an SQL query that count the number of rows?

I am absolutly new in Hibernate and I have the following problem.
I have this standard SQL query:
SELECT count(*)
FROM TID003_ANAGEDIFICIO anagraficaEdificio
INNER JOIN TID002_CANDIDATURA candidatura
ON (candidatura.PRG_PAR = anagraficaEdificio.PRG_PAR AND candidatura.PRG_CAN = anagraficaEdificio.PRG_CAN)
INNER JOIN TID001_ANAGPARTECIPA anagPartecipa ON(anagPartecipa.PRG_PAR = candidatura.PRG_PAR)
INNER JOIN anagrafiche.TPG1029_PROVNUOIST provNuovIst ON (provNuovIst.COD_PRV_NIS = anagPartecipa.COD_PRV_NIS)
WHERE anagraficaEdificio.FLG_GRA = 1 AND provNuovIst.COD_REG = "SI";
This works fine and return an integer number.
The important thing to know is that in this query the only
parameter that can change (inserted by the user in the frontend of a webappplication) is the last one (this one: provNuovIst.COD_REG = "SI").
So, the application on which I am working use Hibernate and the requirement say that I have to implement this query using Hibernate Native SQL, I have found this tutorial:
http://www.tutorialspoint.com/hibernate/hibernate_native_sql.htm
that show this example:
String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
query.setParameter("employee_id", 10);
List results = query.list();
that, from what I have understand (correct me if I am doing wrong assertion), involves the use of an Employee model class. So th prvious query first define the query (using the :param_name syntax for the parameter), then create an SQLQuery Hibernate object, add the class used for the result, set the previous parameter neam and finally obtain a List (that I think Hibernate create as something like an ArrayList) with the retrieved object.
My problem is that I simply I have to obtain an integer value (because I have a SELECT count(*), so I will obtain an integer value and not a set of rows).
So how can I correctly use the Hibernate Native SQL to implement my SQL query into my Hibernate repository class?
Use SQLQuery.uniqueResult to retrieve a single value from the query:
String sql = "SELECT count(*) ...";
SQLQuery query = session.createSQLQuery(sql);
// set parameters...
int count = ((Number)query.uniqueResult()).intValue();

How to update 2 tables using one query in JPA native query?

I have 2 tables TABLE1 and TABLE2.Table1 is having name and Table2 is having email and Phone.
To get the name,email and phone,I query as below
query = entityManagerUtil.createNativeQuery("select s.Name,c.Phone1,c.Email1 from Table1 s,Table2 c where c.id= s.NodeID and s.NodeID =21")
Now my next requirement is to update name,email and phone.As these parameters are present in different tables so I am searching for single query which will update 2 tables.Unfortunately I am using sql server and there is no way to update 2 tables using single query
So I am thinking to use #Transactional and 2 queries to update 2 tables like the follow
#Transactional
public void updateDetails()
{
Query query1= entityManagerUtil.entityManager.createNativeQuery("update Table1 set Name='' where id in (select NodeID from Table 2) and NodeID=21");
Query query2= entityManagerUtil.entityManager.createNativeQuery("update Table2 set Email='' and phone1='' where NodeID in (select id from Table 2) and NodeID=21");
query1.executeUpdate();
query2.executeUpdate();
}
Is there any other better way to update 2 tables?
you can use JDBCTemplate
http://sujitpal.blogspot.com.es/2007/03/spring-jdbctemplate-and-transactions.html
It allows to do multiple queries with one connection, so you save some time instead of doing it twice.
Why don't you use Hibernate entities for that. Just load the entities associated with Table1 and table2, modify them and let the automatic dirty checking mechanism to update the tables on your behalf. That's one reason for using an ORM by the way.

Spring Data JPA, hibernate: update all query and SET value by selecting from another table

Is the following SQL possible in a JPA query? I tried but the actual SQL hibernate runs doesn't seem right.
This is the SQL i want to write as JPA query;
UPDATE movie m SET average_rating = COALESCE((SELECT AVG(stars) FROM rating r WHERE r.movie_id = m.id), 0);
This is the JPA query;
#Query("UPDATE Movie m SET m.averageRating = COALESCE((SELECT AVG(r.stars) FROM Rating r WHERE r.movie = m), 0)")
And what hibernate says;
Hibernate:
insert
into
HT_Movie
select
movie0_.id as id
from
Movie movie0_
Hibernate:
update
Movie
set
average_rating=coalesce((select
avg(rating1_.stars)
from
Rating rating1_
where
rating1_.movie_id=id),
0)
where
(
id
) IN (
select
id
from
HT_Movie
)
so there seems to be an additional where being added by hibernate.
#Query("UPDATE Movie m SET m.averageRating = COALESCE((SELECT AVG(r.stars) FROM Rating r WHERE r.movie = m), 0)")
This is 100% correct.
And hibernate works correctly as well.
Hibernate works in this way:
Create a temporary table HT_Movie and insert the ids of Movie table.
Create the JPA query as a whole where
Compare abstracting ids from HT_Movie t enforce more speed in update processing
And this is not new hibernate always fabricates queries.

Hibernate Criteria join to table containing foreign key

I have two tables:
Client (clientId, firstName, lastName, gender)
Event (clientId, eventId)
I need to represent a query similar to the following using Criteria:
SELECT c.clientId, c.firstName, c.lastName, c.gender, MAX(eventId)
FROM Client c JOIN Event e ON c.clientId = e.clientId
GROUP BY c.clientId, c.firstName, c.lastName, c.gender
I have tried this:
final Criteria criteria = session.createCriteria(Client.class);
criteria.setFetchMode("Event", FetchMode.JOIN);
criteria.setProjection(Projections.projectionList().add(Projections.groupProperty("clientId")).add(Projections.max("eventId")));
but it throws an exception on the last line with the message:
HibernateQueryException: could not resolve property: eventId of:
Client
How can I specify the join between the Client table which itself contains no column related to the Event table but the clientId column on the Event table is a foreign key back into the Client table?
As you can see, it's really driven off the Client table and that I only need to select the maximum eventId from the Event table. Also, as I mentioned, I am trying to make a change to an existing Criteria query which is based on the Client class. It is used to retrieve all the columns for all active clients. I just need to add one extra column to the query results - the maximum eventId.
Use alias
Criteria criteria = session.createCriteria(Event.class, "et").
createAlias("et.Client", "ct").
setProjection(Projections.projectionList().
add(Projections.groupProperty("et.clientId")).
add(Projections.max("et.eventId")));
For more details on criteria, refer Criteria Queries
That is obvious. Because Client class does not have eventId property, and your criteria is defined for Client class.
When trying to use a property of B class inside a Criteria for A, you have to use Aliases.
All you have to do is to modify your code like this:
final Criteria criteria = session.createCriteria(Event.class, "event");
criteria.createAlias("event.client", "client");
criteria.setProjection(Projections.projectionList().add(Projections.groupProperty("clientId")).add(Projections.max("eventId")));
UPDATED (based on your comment)
As your query needs Event class, you have to have a Criteria for this class. So you have to something like this:
final Criteria criteria = session.createCriteria(Event.class, "event");
criteria.createAlias("event.client", "client");
//The criteria below, is returning clientId
DetachedCriteria eventCr = DetachedCriteria.forClass(Event.class, "event");
eventCr.setProjection(Projections.projectionList().add(Projections.groupProperty("clientId")).add(Projections.max("eventId")));
//Now using subqueries you can achieve your goal
criteria.add(Subqueries.propertyIn("clientId", eventCr));
I don't know for sure what you're looking for, but I hope I have given you some good hints. You might want to try Subqueries.propertyEq instead if your query must return a single id.

Categories

Resources