How to select one table using NHibernate CreateCriteria - nhibernate

How can I create the following SQL statement in Nhibernate using CreateCriteria:
SELECT distinct top 20 a.* from ActivityLog a
left join WallPost w on a.ActivityLogId = w.ActivityLogId left join ItemStatus i on i.StatusId = w.ItemStatus
I always tend to get all columns from all tables returned in the sql statement producing duplicates even though I map it to the ActivityLog table. I am also doing paging as the code below shows:
ICriteria crit = nhelper.NHibernateSession.CreateCriteria(typeof(Model.ActivityLog), "a").CreateAlias("a.WallPosts", "w",CriteriaSpecification.LeftJoin)
.CreateAlias("w.ItemStatus", "i", CriteriaSpecification.LeftJoin)
.SetMaxResults(pageSize).SetFirstResult(startRow).AddOrder(Order.Desc("a.Date"));
Thanks
H

Sounds like you have set lazy loading to false in your mapping files meaning that all the associations and child collections are being loaded up too. Can you verify that?

You ask "How to select one table using NHibernate CreateQuery" (HQL). In that case you can choose what to fetch using select.
In your text you're using criteria. AFAIK, you cannot directly control what columns you want to read. However, if you create a DetachedCriteria for the join, this won't be fetched.

Related

nhibernate - Incorrect generated SQL when running count w/ a join

All,
I am using Nhibernate 3.3, asp.net 2.0.
The HQL below is incorrectly translated to the SQL ONLY when I run the count query, in other words, I run 2 queries:
1) First query to query result
2) Same query but change the select columns, to select count(*)
It appears my joins are gone but I need them for filtering!
Do you think the 'fetch' keyword is screwing things up? I technically don't need "fetch" in the query when I am doing count() but need it for the first query.
HQL before running it:
select count(legal.id) from OtherRPlan_ p
inner join fetch p.IssuedBy
left join fetch p.Region
left join fetch p.LegalDescList legal
where p.Status = true and p.Region.Id = :region
Generated SQL from HQL:
select count(legaldescl3_.entity_id) as col_0_0_
from Other_Rplans otherrplan0_
where otherrplan0_.status=1 and otherrplan0_.region_id=#p0
Found the cause of the error:
The use of 'fetch' keyword in the query causes this behavior. I know it doesn't make sense to use 'fetch' in count() but when building queries dynamically you try to re-use as much code (that should be the same in both queries) as possible for ease of maintenance and consistency.

Joining tables to fill lists of entities

I am using JPA and Hibernate, but my need is too complicated to build a HQL, at least for me.
I decided to use native SQL.
I need to get some records/entities with their child lists but, i need to filter childs, i do not want all the childs.
Is this possible?
For example i have three tables like
conversation_table:
id
mail_table:
id, conversation_id, sender_id
user_table:
id, married_bool
I need conversation entities having lists that filled by mails those are send by married users.
I tried so far
Select * from conversation_table join mail_table on ( mail_table.sender_id=user_table.id and user_table.married_bool=true)
I am getting an error like:
user_table is unknown
I tried
Select * from (conversation_table, user_table, mail_table) join mail_table on ( mail_table.sender_id=user_table.id and user_table.married_bool=true)
I am getting
mail_table is non unique table/alias
This is only a light example, also need to fill some entity lists of mail entity in other tables for example recipient_table, i think i have to add join clauses for filling these too in native query, am i right? Also i am getting 'not known'/'non unique alias' errors, when try this additional join clauses.
Thanks for suggestions.
Something like this:
SELECT *
FROM conversation_table CT
JOIN mail_table MT
ON CT.Id = MT.conversation_id
JOIN user_id UI
ON MT.sender_id=UI.id
WHERE UT.married_bool = 1
If you really want to use Hibernate ORM for this query they Criteria Query is the best approach for this. Recently, i have the same requirement and have used Criteria only.

NHibernate HQL subselect left join?

I have the following issue and I would really appreciate your help:
I have all my filtering done through the HQL and one of the filters is a left outer join which must be a sub-select. So my thinking here is that I can create a dummy business object which I would like to populate (with an SP if possible) with data and use it in my left join.
Now how can I do that and still have all of the logic in 1 HQL query?
I guess the biggest issue for me is understanding how can I have this BO (not actually mapped to a table etc.) be used in a query where all the other BOs are mapped to tables etc.
I am trying to avoid doing any filtering in the actual C# code.
Thanks!
Example:
Entity A - mapped to table A
Entity B - mapped to table B
Entity C - mapped to table C
Entity D - not mapped to table - coming from SQL query or SP
HQL:
from A pbo
inner join B.EntityType etype
inner join C.EntityAddressList eadr
left join D.Level lvl
You cannot join to arbitrary SQL in HQL. So I don't think what you're trying to do is possible. You'll likely either have to map whatever D is, or write your query in SQL using Session.CreateSQLQuery(). You can still specify any entities that come back. See this article for reference. http://www.nhforge.org/doc/nh/en/index.html#d0e10274

How to implement paging in NHibernate with a left join query

I have an NHibernate query that looks like this:
var query = Session.CreateQuery(#"
select o
from Order o
left join o.Products p
where
(o.CompanyId = :companyId) AND
(p.Status = :processing)
order by o.UpdatedOn desc")
.SetParameter("companyId", companyId)
.SetParameter("processing", Status.Processing)
.SetResultTransformer(Transformers.DistinctRootEntity);
var data = query.List<Order>();
I want to implement paging for this query, so I only return x rows instead of the entire result set.
I know about SetMaxResults() and SetFirstResult(), but because of the left join and DistinctRootEntity, that could return less than x Orders.
I tried "select distinct o" as well, but the sql that is generated for that (using the sqlserver 2008 dialect) seems to ignore the distinct for pages after the first one (I think this is the problem).
What is the best way to accomplish this?
In these cases, it's best to do it in two queries instead of one:
Load a page of orders, without joins
Load those orders with their products, using the in operator
There's a slightly more complex example at http://ayende.com/Blog/archive/2010/01/16/eagerly-loading-entity-associations-efficiently-with-nhibernate.aspx
Use SetResultTransformer(Transformers.AliasToBean()) and get the data that is not the entity.
The other solution is that you change the query.
As I see you're returning Orders that have products which are processing.
So you could use exists statement. Check nhibernate manual at 13.11. Subqueries.

nhibernate cross table query optimization

I have a query I've written with NHibernate's Criteria functionality and I want to optimize it. The query joins 4 tables. The query works, but the generated SQL is returning all the columns for the 4 tables as opposed to just the information I want to return. I'm using SetResultTransformer on the query which shapes the returned data to an Individual, but not until after the larger sql is returned from the server.
Here's the NHibernate Criteria
return session.CreateCriteria(typeof(Individual))
.CreateAlias("ExternalIdentifiers", "ExternalIdentifier")
.CreateAlias("ExternalIdentifier.ExternalIdentifierType", "ExternalIdentifierType")
.CreateAlias("ExternalIdentifierType.DataSource", "Datasource")
.Add(Restrictions.Eq("ExternalIdentifier.Text1", ExternalId))
.Add(Restrictions.Eq("ExternalIdentifierType.Code", ExternalIdType))
.Add(Restrictions.Eq("Datasource.Code", DataSourceCode))
.SetResultTransformer(new NHibernate.Transform.RootEntityResultTransformer());
And the generated sql (from NHProfiler) is
SELECT (all columns from all joined tables)
FROM INDIVIDUAL this_
inner join EXTERNAL_ID externalid1_
on this_.INDIVIDUAL_GUID = externalid1_.GENERIC_GUID
inner join EXTERNAL_ID_TYPE externalid2_
on externalid1_.EXTERNAL_ID_TYPE_GUID = externalid2_.EXTERNAL_ID_TYPE_GUID
inner join SYSTEM_SRC datasource3_
on externalid2_.SYSTEM_SRC_GUID = datasource3_.SYSTEM_SRC_GUID
WHERE externalid1_.EXTERNAL_ID_TEXT_1 = 96800 /* #p0 */
and externalid2_.EXTERNAL_ID_TYPE_CODE = 'PATIENT' /* #p1 */
and datasource3_.SYSTEM_SRC_CODE = 'TOUCHPOINT' /* #p2 */
I only want the columns back from the Individual table. I could set a projection, but then I lose the Individual type.
I could also rewrite this with DetachedCriteria.
Are these my only options?
I had exactly the same question and asked one of NHibernate development team members directly, here is the answer I got:
with the Criteria API, the only thing you could do is to use a projection list and include all of the properties of the root entity... then you would need to use the AliasToBeanResultTransformer. Far from an optimal solution obviously
if you don't mind rewriting the query with hql, then you can do it very easily. an hql query that says "from MyEntity e join e.Association" will select both the entity columns as well as the association's columns (just like the problem you're having with criteria). But an hql query that says "select e from MyEntity e join e.Association" will only select the columns of e.