Named Queries en NHibernate y por qué debemos usarlas
En chat con Fabio Maulo, me estaba contando de las bondades de usar Named Queries en NHibernate, las cuales justifican esta entrada en el blog.
Que es una named query? Es una query que se define en los archivos de mapeos y posee un nombre, puede ser HQL o SQL nativo. Una HQL query puede ser escrita asÃ:
<query name="Foo-by-name" cacheable="false" read-only="true"> <![CDATA[ from Foo where Name like :value ]]> </query>
Y la named query equivalente en Sql Nativo se puede escribir de esta manera:
<sql-query name="Foo-by-name" cacheable="false" read-only="true"> <return alias="foo" class="Foo"/> <![CDATA[ SELECT {foo}.ID AS {foo.Id}, {foo}.NAME AS {foo.Name}, {foo}.MISC AS {foo.Misc} FROM Foo {foo} WHERE {foo}.Name LIKE :value ]]> </sql-query>
El código que lo ejecuta:
Foo f1 = new Foo(); f1.Misc = "misc 1"; f1.Name = "foo 1"; session.Save(f1); Foo f2 = new Foo(); f2.Misc = "misc 2"; f2.Name = "foo 2"; session.Save(f2); session.Flush(); IQuery q = session.GetNamedQuery("Foo-by-name"); q.SetString("value", "f%"); Debug.Assert(q.List().Count == 2);
Si se dan cuenta, ambas Named Queries se ejecutan con el mismo código
Ventajas:
- Si queremos cambiar de motor de base de datos, no tenemos que cambiar la query nativa en el código, sino en el mapping.
- Si poseemos queries escritas en HQL y queremos usar alguna feature especial del motor, solo debemos escribir una named query equivalente en SQL nativo y usarla.
- Muy importante! Y practicamente La Razón de este post. Las named queries se parsean 1 sola vez, cuando se llama al .BuildSessionFactory(); de modo que si escribimos mal la query (por que nos equivocamos en el nombre de una property por ejemplo), NHibernate nos va a avisar con un error. Las otras queries se parsean TODAS las veces que van a hacer ejecutadas, a menos que estén en una caché destinada a ellas. Esta es una caché MRU (Most Recently Used) de 128 posiciones.
- El código queda más limpio !
- Se evita la construcción de los queries artesanalmente y variables, haciendo uso y abuso de String.Format( … ), gastando posiciones en la caché MRU para estas queries.
Gracias Fabio por la información.
Como no me quedó claro intento aclarar…
La cache MRU es gestionada directamente por NH esto significa que si se usan queries estritas en el codigo en lugar que en el mapping NH se ocupa de parsearlas lo menos posible; de hecho si las queries escritas en el codigo son menos de 128 NH la parsea una sola vez como hace por la named-queries.
Otra cosita….
No se si has usado alguna vez los filters… todo este discurso se aplica tambien a los filters.
[...] cosas que no son relevantes en este post). El mapear queries en Xml se llama: Named Queries, y en este post hablamos un poco más de sus bondades. Pero el punto principal aquà es, que mapeando las queries [...]