views:

57

answers:

2

Hello Guys, I'm developing an application with nHibernate and MySQL.

I have a HQL command that runs every second, and in this command I do a "Inner Join Fetch", like this:

"from Order o inner join fetch o.Customer order by o.Date"

It's work fine but It fill all properties of "Customer", and I have a lot of columns in DataBase (almost 40 columns). I need only some columns like Name, Address and Telephone to show in my presentation layer.

Is there any way to get only some properties doing a Fecth Join or another way to improve performace?

Thanks...

Cheers

+2  A: 

You could make a secondary read-only mapping that only fetches part of the columns into a Dto (Data Transfer Object):

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Your.NameSpace" assembly="Your.Assembly">
  <class name="OrderDto" table="[Order]" schema-action="none" lazy="false" mutable="false">
  <id name="Id">
    <generator class="native"/>
  </id>
  <many-to-one name="CustomerDto" class="CustomerDto"/>
  <!-- Other properties-->
  </class>
</hibernate-mapping>

This way - you get full control over what gets pulled out of the DB. There is a flip-side though - make sure that it is marked as mutable="false" or you could potentially save it without the full data.

And if you really want to get crazy - you make the OrderDto implement the same interface as the normal Order - and then when asking for a property not already loaded - you fetch the full order. This adds a fair bit of complexity, but you get an extreme amount of flexibility as well as being able to use the Dto in place of the real object with all the performance benefit of the Dto. (This is also known as the Proxy pattern whereas the first bit is sometimes called a PresentationModel as it is tailored for presentation without the normal business-logic.)

Goblin
hmm, doesn't non-mutable only mean you cannot update it. I don't think it stops you from inserting...
dotjoe
@dotjoe: Correct - but it is updating that is potentially dangerous with PresentationModels. E.g. if you get a flush from a property not being correctly converted during the querying. (Enum to int32 e.g.)
Goblin
very true...it would be much harder to accidentally insert.
dotjoe
+2  A: 

If you are looking for some properties only, don't use join fetch, because that's not what it's for.

Instead, select the properties you want and (optionally) hydrate a DTO with them. You don't even need an explicit join:

select o, o.Customer.Name, o.Customer.Address
from Order o
order by o.Date

That returns a tuple (object[]) for each row, where the 1st element is the order, the 2nd is the customer name, etc.

Diego Mijelshon
Hi Diego, thanks! I'm trying to do this: "select new Dto(o.Customer.Name, o.Location, ...) from Order o", but NHibernate give an exception that say I don't map my DTO object. How could I map this DTO with Fluent NHibernate ? I tried to map with ImportType<Dto> in a simple class inhereting from ClassMap<Dto> but it doesn't work!
Felipe
I'm not big on Fluent. Anyway, you can just assign an alias to each element of the select list, and then apply ´.SetResultTransformer(Transformers.AliasToBean<YourDTO>())´
Diego Mijelshon
Thanks Diego! NHibernate is amazing! Cheers!
Felipe