NHibernate and reporting - nhibernate

I am building a website on top of nhibernate. Is there any efficient way to build reports? BY reports, I mean is there anyway to execute a complicated query that grabs random pieces of data? Stored procedures? Hql?
Can I get single, non mapped values from hql?

Yes you can.
For simple stuff you can use HQL and select stuff into a new non-mapped object (its class must be "registered" with NH but there is no mapped per se). HQL syntax looks like
select new NonMappedClass(column1, column2). You need an appropriate constructor to use this.
Reporting with HQL quickly breaks down. I often find myself knowning exactly what to do in SQL but having hard time figuring out the HQL way. Also the lack of real software tools for HQL slows you down (sorry NH Query Analyzer does not cut it). In these case, you can define a raw with an associated . When executing these queries, NH will return you a IList of array of Object. You need the cast the Object() into the proper type. You'll want this for advanced reporting queries.
This casting stuff is error prone and sucks big time. So you they did a nice AliasToBean query transformer that can map the result set column name to a property (names must match of course). I don't know about the latest NH release, but the older 1.2.1 AliasToBean converter seemed to have a bug in which it would converter nullable value type to the default value of the type instead of setting it to null. ie: int? would be 0 instead of null if the associated DB field was null. This prevented me from using AliasToBean in some case and I had to map by hand.
Best advice is don't fall into the trap of performing complex reporting with your business object and for loops. I've seen this in production. It will be a performance horror as your tables grows in size.

Yes, you can do this. It's called dynamic instantiation. The syntax in HQL is
select new MyClass(cust.age)
from customers cust
Or, with Criteria:
.SetProjection(Projections.ProjectionList()
.Add(Projections.Name("cust.age"), "age")
.SetResultTransformer(Transformers.AliasToBean<MyClass>())
Remember, you must have a matching constructor on MyClass!

Related

What's the common practice in constituting the WHERE clause based on the user input

If we take a database table, we can query all the rows or we can choose to apply a filter on it. The filter can vary depending on the user input. In cases when there are few options we can specify different queries for those few specific conditions. But if there are lots and lots of options that user might or might not specify, aforementioned method does not come handy. I know, I can compose the filter based upon the user input and send it as a string to the corresponding stored procedure as a parameter, build the query with that filter and finally execute the query string with the help of EXECUTE IMMEDIATE(In Oracle's case). Don't know why but I really don't like this way of query building. I think this way I leave the doors open for SQL injectors. And besides, that I always have trouble with the query itself as everything is just a string and I need to handle dates and numbers carefully.What is the best and most used method of forming the WHERE clause of a query against a database table?
Using database parameters instead of attempting to quote your literals is the way forward.
This will guard you against SQL injection.
A common way of approaching this problem is building expression trees that represent your query criteria, converting them to parameterized SQL (to avoid SQL injection risks), binding parameter values to the generated SQL, and executing the resultant query against your target database.
The exact approach depends on your client programming framework: .NET has Entity Framework and LINQ2SQL that both support expression trees; Java has Hibernate and JPA, and so on. I have seen several different frameworks used to construct customizable queries, with great deal of success. In situations when these frameworks are not available, you can roll your own, although it requires a lot more work.

NHibernate problem choosing between CreateSql and CreateCriteria

I have a very silly doubt in NHibernate. There are two or three entities of which two are related and one is not related to other two entities. I have to fetch some selected columns from these three tables by joining them. Is it a good idea to use session.CreateSql() or we have to use session.CreateCriteria(). I am really confused here as I could not write the Criteria queries here and forced to use CreateSql. Please advise.
in general you should avoid writing SQL whenever possible;
one of the advantages of using an ORM is that it's implementation-agnostic.
that means that you don't know (and don't care) what the underlying database is, and you can actually switch DB providers or tweak with the DB structure very easily.
If you write your own SQL statements you run the risk of them not working on other providers, and also you have to maintain them yourself (for example- if you change the name of the underlying column for the Id property from 'Id' to 'Employee_Id', you'd have to change your SQL query, whereas with Criteria no change would be necessary).
Having said that- there's nothing stopping you from writing a Criteria / HQL that pulls data from more than one table. for example (with HQL):
select emp.Id, dep.Name, po.Id
from Employee emp, Department dep, Posts po
where emp.Name like 'snake' //etc...
There are multiple ways to make queries with NH.
HQL, the classic way, a powerful object oriented query language. Disadvantage: appears in strings in the code (actually: there is no editor support).
Criteria, a classic way to create dynamic queries without string manipulations. Disadvantages: not as powerful as HQL and not as typesafe as its successors.
QueryOver, a successor of Criteria, which has a nicer syntax and is more type safe.
LINQ, now based on HQL, is more integrated then HQL and typesafe and generally a matter of taste.
SQL as a fallback for cases where you need something you can't get the object oriented way.
I would recommend HQL or LINQ for regular queries, QueryOver (resp. Criteria) for dynamic queries and SQL only if there isn't any other way.
To answer your specific problem, which I don't know: If all information you need for the query is available in the object oriented model, you should be able to solve it by the use of HQL.

HQL vs. SQL / Hibernate netbeans HQL editor

I am teaching my self hibernate, and am quite confused of why i can not just write simple SQL queries.
I find it rather more confusing to use than plain SQL (what I am used to)
PLUS: The NetBeans HQL editor I found pretty annoying, It is harder for me to produce a right query in HQL, then in SQL, and why does the shown SQL differ from actual SQL statements ?
So why use it ? - As it is known that hibernate is very resource extensive, and I believe that hibernate is the reason for our app to running out of memory very often, as during the process of redeploying e.g...
I am very interested in knowing why I should use Hibernate and not plain SQL (mysql) statements !?
And maybe a good link for hibernate queries would be nice ;), I am using this one atm:
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html
But also interested in any good link explaining the setup of the queries, the mapping, underlying construction etc..
Best Regards
Alex
HQL is object oriented and it's done with the purpose of working on the Java objects representing your DB tables.
A basic advantage is that you can put placeholders like :orderNumber (using the colon simbol) in the HQL query and replace with the value of a variable. For example:
int orderNumber = 685412;
List<Order> l=
session.createQuery("from Order where orderNumber = :orderNumber")
.setParameter("orderNumber",orderNumber).list();
In this way you can modify orderNumber in a simple way, evoiding the classical
String query = "select * from Order where orderNumber = " + orderNumber + "...";
Morover using MySQL syntax would sometimes turn your code not reusable if you migrate your DB to another DBMS.
Anyway I'm still not so convinced about the preference on HQL.
Here you can find the full grammar definition.

EntitySet Querying

I'm trying to run a query similar to
var results = MyItem.MyEntitySet.Where( x => x.PropertyB == 0 )
MyEntitySet has one association, PropertyA, with MyItem.
Ideally, the underlying SQL query should be
SELECT .. FROM .. WHERE ([t0].[PropertyA] = #p0) AND ([t0].[PropertyB ] = #p1)
since PropertyA and PropertyB are the two primary keys of the table I'm querying.
But my traces seem to indicate that the program queries with PropertyA first to return MyEntitySet, then queries with PropertyB to return var results.
Is there anyway I can force Linq to query with these two conditions in a single SQL statement?
Maybe, maybe not. The generated SQL does match the way you're writing the LINQ query, so the generated SQL isn't a surprise. If you started with the entity represented by "MyEntitySet" then, maybe, the generated SQL would change.
It's not immediately clear whether you're using LINQ to SQL or Entity Framework. LINQ to SQL does represent one-to-many relationships as an "entity set", while Entity Framework treats relationships as first-class objects, so that a one-to-many relationship is a set of relationship objects with related entities, rather than simply an entity set. It does affect the generated SQL.
Two other thoughts...
If you want that much control over the generated SQL, you probably won't be happy with LINQ. It doesn't always generate optimal SQL (although it can sometimes surprise you). On the other hand, one of the major benefits of LINQ is that you start writing code that expresses the real relationships in your data. The downfall of classic ADO.NET is that you write code about manipulating SQL and processing DataSet and DataTable collections. LINQ is infinitely cleaner, safer, more robust, and more maintainable code to write. Everything is a trade-off.
Second, the query generation is likely to get better over time (especially in Entity Framework).

Temporal data using NHibernate

Can anyone supply some tips/pointers/links on how to implement a temporal state-table with NHibernate? I.e., each entity table has start_date and end_date columns that describe the time interval in which this this row is considered valid.
When a user inserts a new entity, the start_date receives 'now' and the end_date will be null (or a date far into the future, I haven't decided yet).
When updating, I'd like to change the UPDATE query into the following:
UPDATE end_date for this entity's row, and
INSERT a new row with the current date/time and a null end_date.
I tried using event listeners to manually write an UPDATE query for 1, but can't seem to figure out how to implement a new INSERT query for 2.
Is this the proper way to go? Or am I completely off-mark here?
Actually we have a working solution were i work but it effectively kills a part of the nhibernate's mechanism.
For 'temporal entities' NH acts only as an insert/select engine. Deletes and updates are done by a different utility where the ORM part of NH comes handy.
If you only have a handful of temporal entities you may only use nhibernate but be prepared to write your own code to ensure state relations are valid.
We went that route in our first try and after the number of temporal entities started adding up the mechanism was effectively broken.
Now, inserts don't need no special tooling, just place the values in the appropriate datetime properties and you're set. We implement selects with Filters (definitely check 16.1 of NH ref as it has an example, but the condition must not use a BETWEEN) although if you go that way you will have to modify the NH source code to apply filters on all kinds of selects.
Check my post at http://savale.blogspot.com/2010/01/enabling-filters-on-mapped-entities.html for doing that.
It might also work if you specify the "where" clause on the mapping (instead of filters) but i haven't tried or tested it yet, and it is my understanding that the mapped "where" on the mapping do not support parameters (at least not officially).
As i side note, the reason for using a custom tool for updates/deletes will become clear once you have read Richard Snodgrass's books on temporal databases http://www.cs.arizona.edu/~rts/publications.html
To directly answer your question, both the NULL _end value and a value far in the future will work (but prefer the NOT-NULL solution it will make your queries easier as you will not have to check with ISNULL).
For updates you effectively make a clone of the original entity then set the original entity's _end to now, and then go to the cloned and change the relevant properties, change _start to now, _end to the far-in-the-future value
I suggest the excellent timeNarrative from Martin Fowler.
I think the best approach is to have something like a Java map (sorry, I'm a Java programmer) and let NHibernate to map that. The map would map something like a Period, with a "start" and "end" fields, to a value. You can the write a UserType to map the Period to two different database columns
While this article is a few years old, the pattern still seems valid. I have not yet used this but I need a similar solution in a current project and will be modeling it the way it is described here.