Complex SQL query to Hibernate HQL statement - java

Following SQL query:
select distinct hotel.country 'Country', hotel.id 'Hotel ID', hotel.Name'Name', room.id 'Room ID'
from room, stay, reservation, hotel
where
(stay.roomid = room.id)
and (stay.reservationid = reservation.id)
and (reservation.status != 'Booked' AND reservation.status != 'CheckedIn')
and (reservation.arrivaldate >= '2012-08-08')
and (reservation.leavedate <= '2012-08-15')
and (room.hotelid = hotel.id)
order by hotel.country, hotel.id, hotel.name, room.id asc
This will give me a list of available rooms per hotel per country. Now I have to put this in HQL, but I can't do so because of this:
Query query = session.createQuery("from room, stay, reservation, hotel where stay.roomid = room.id");
This doesn't work becuase stay.roomid is a Room object whereas room.id is just an integer. I'm pretty new to Hibernate/HQL and the reference manual didn't really bring me anywhere... How can I "convert" (scary word, I know this doesn't involve actual converting) this SLQ query to a HQL statement? Thanks.
UPDATE
Using a join result in the same problem
Query query = session.createQuery("" +
"from Stay stay " +
"join stay.ReservationID reservation " +
"join stay.RoomID room " +
"join room.HotelID hotel " +
"where (stay.RoomID = room.ID)");
I'm really missing something (probably very logical) here...

You haven't shown your entities, but, just as you would use joins in SQL, you need to use joins in HQL:
select ...
from Stay stay
join stay.reservation reservation
join stay.room room
join rom.hotel hotel
where (reservation.status != 'Booked' AND reservation.status != 'CheckedIn')
and (reservation.arrivaldate >= '2012-08-08')
and (reservation.leavedate <= '2012-08-15')
The Hibernate documentation has a whole chapter on HQL, and a section of this chapter about associations in HQL.

Related

How do I write join in Ebean Java ORM language

Currently my code is
int customerId = 4;
String sql = "select id from coupon as A join coupon_use "
+ "as B on A.id=B.coupon where B.customer=" + customerId
+ " and B.like_at is not null;";
RawSql rawSql = RawSqlBuilder.parse(sql).create();
Query<Coupon> query = Ebean.find(Coupon.class);
query.setRawSql(rawSql);
List<Coupon> list = query.findList();
return ok(Json.toJson(list));
How do I avoid writing manual sql query but still have the ORM generate that query and return me the result?
Ebean will add appropriate joins based on the paths/properties used in the where and order by etc.
where couponUse.likeAt is not null.
Assuming couponUse.likeAt is the correct expression path ... Ebean will add a join to support the expression automatically.

Hibernate Criteria with joins not generating correct SQL

I'm trying to execute a Criteria query but when I execute the code, the SQL only brings up company_synonym in the from clause, not the other two.
The mappings are:
Company has 1-to-Many CompanySynonyms
Company has 1-to-Many CompanyProductRoles
I want the query to return CompanySynonym objects, so I tried this:
Criteria criteria = session.createCriteria(CompanySynonym.class, "cs")
.createAlias("cs." + CompanySynonym.COMPANY, "cmp")
.createAlias("cmp." + Company.COMPANY_PRODUCT_ROLE, "cpr")
.add(Restrictions.eq("cs." + CompanySynonym.TYPE, "1234"))
.add(Restrictions.eq("cpr." + CompanyProductRole.PRODUCT_ID, Integer.valueOf(productId)))
.add(Restrictions.isNotNull("cpr." + CompanySynonym.Company_ID))
.add(Restrictions.eq("cpr." + CompanyProductRole.ROLE_CODE, "AB"));
And it generates this SQL:
select this_.company_syn_id_i as company1_0_0_, this_.company_id_i as company5_0_0_, this_.cmp_syn_end_d as cmp2_0_0_, this_.cmp_syn_type_cd_c as cmp3_0_0_, this_.cmp_syn_c as cmp4_0_0_
from product.dbo.company_synonym this_
where this_.cmp_syn_type_cd_c=?
and cpr1_.product_id_i=?
and cpr1_.company_id_i is not null
and cpr1_.role_cd_c=c
What am I missing or doing wrong here?

Setting ORDER BY and LIMIT clause on JPA Query

I'm very, very new to Hibernate and JPA. I want to be able to apply ORDER BY and LIMIT clauses to a Hibernate(?) query, but am coming up empty. NOTE: I inherited this code.
Here is the current code:
public SomeCoolResponse getSomeCoolResponse(String myId) {
String queryString = "select aThing from AWholeBunchOfThings aThing " +
"join aThing.thisOtherThing oThing join oThing.StillAnotherThing saThing " +
"where saThing.subthing.id = :id";
Query q = getEntityManager().createQuery(queryString);
q.setParameter("id", myId);
List<MyThings> list = q.getResultList();
if(list.size() > 0) {
return list.get(0);
}
return null;
}
Instead of getting an entire list and then just returning the first result (which is the only one we need), I'd like to be able to apply a LIMIT 0,1 clause so that the query will be faster. Also, the query needs to be sorted descending on aThing.created which is a UNIX timestamp integer.
I've tried altering queryString like this:
String queryString = "select aThing from AWholeBunchOfThings aThing " +
"join aThing.thisOtherThing oThing join oThing.StillAnotherThing saThing " +
"where saThing.subthing.id = :id ORDER BY aThing.created LIMIT 0,1";
But Hibernate still returns the entire set.
I've looked at using the JPA CriteriaBuilder API, but it hurt my brain.
I'm a total n00b when it comes to this, and any help is greatly appreciated!
I think you need
q.setMaxResults(1);
See also the accepted answer here.
How do you do a limit query in HQL?
As to the "order by" clause you may include it in the queryString.
The JPQL equivalent to LIMIT start,max is:
setFirstResult and setMaxResults:
q.setFirstResult(start);
q.setMaxResults(limit);

JPA avoiding multiple subquery

I need a little help setting up my query. I don't want to have to make multiple selects to form basically the same sub-query if I can avoid it. In a nut shell, I have Objects called TimeSlot that are used to track several details. Those TimeSlot's are items that are paid on. When its time for the TimeSlot to submit for a reimbursement they are used to create a PayableTimeSlot. Before the TimeSlot can be paid I need to make sure it has not been paid already.
As it sits the following is my query:
#NamedQuery(
name = "TimeSlot.by.person.academy.id.by.contract.date",
query = "select distinct ts
from TimeSlot ts
join ts.invitedInstructors ii
join ts.academyClass ac
join ac.academy a
where ii.person.id = ?
and a.id = ?
and ts.schedule.startDateTime BETWEEN ? AND ?
and ts.id not in (select e.id from PayableTimeslot pts join pts.event e)
and ? not in (select e.claimant from PayableTimeslot pts join pts.event e)")
As you can see I am already selecting an element from the PayableTimeSot for the first not in. Is there a way to expand the sub-query into:
(select e.id, e.claimant from PayableTimeslot pts join pts.event e) I am just not sure how to check for multiple items not in the sub-query. By all means if there is a better attack of the problem than the way I am doing it let me know.
Unless you all think the multiple selects wont be a big deal... There will be on average 30-50 entry's a week into the table with each entry being copied (for an audit trail) upwards of 7-9 times.
Okay so after some thinking this is what I came up with. I was indeed trying to answer the problem in the wrong way... I was doing two sub querys when all I needed was a where on the first thus combining the two.
#NamedQuery(
name = "TimeSlot.by.person.academy.id.by.contract.date",
query = "select distinct ts "
+ "from TimeSlot ts "
+ "join ts.invitedInstructors ii "
+ "join ts.academyClass ac "
+ "join ac.academy a "
+ "where ii.person.id = ? "
+ "and a.id = ? "
+ "and ts.schedule.startDateTime BETWEEN ? AND ? "
+ "and ts.id not in (select e.id from PayableTimeslot pts join pts.event e where pts.claimant = ?)")

How do I port query with join across multiple tables from JDOQL to HQL

I am porting an application for KodoJDO to Hibernate.
I have a query that goes across 4 tables in the db, and 3 objects in the java code.
In English the query is Find the users that have entitlements in system X.
my JDOQL where clause called on the User object was
where entitlements.contains(ent) && (upper( ent.system.id ) = 'EVPN')
some sql that does the query is:
select unique(u.id)
from USER u, USERENTITLEMENT ue, ENTITLEMENT e, SYSTEM s
where u.id = ue.userid
and ue.entitlementid = e.id
and e.systemid = s.id
and s.id = 'evpn'
My best guess for HQL gives me an exception
org.hibernate.hql.ast.QuerySyntaxException: unexpected AST node: ( [select user from com.ebig.entity.User as user, com.ebig.entity.Entitlement as ent, com.ebig.entity.System as sys where entitlements.contains(ent) and ent.system = sys and sys.id = 'evpn']
the db is structured like this:
User
id
UserEntitlement
userid
entitlementid
Entitlement
id
systemid
System
id
the java code is structured as below:
class User
{
String id;
Set<Entitlement> entitlements;
}
class Entitlement
{
String id;
System system;
}
class System
{
String id;
}
Update My final query that works
hqlQuery = "select distinct user from User as user "+
"inner join user.entitlements as entitlement inner join entitlement.system as system "+
"where system.id = 'evpn' AND mod(user.flags, 2) = 0 AND source = 1";
Yes I know I should use parameters, but I have a great many problems to solve, and will post pone that code for another day.
Another variation with an implicit inner join for entitlement to system
hqlQuery = "select distinct user from User as user "+
"inner join user.entitlements as entitlement "+
"where entitlement.system.id = 'evpn' AND mod(user.flags, 2) = 0 AND source = 1";
You should use joins :
select distinct u.id from User u
inner join u.entitlements as entitlement
inner join entitlement.system as system
where system.id = :evpn
where :evpn is a named parameter that you have to bind.
You must think in terms of objects and relationships between objects when doing HQL, and not in terms of tables, foreign keys and join tables.

Categories

Resources