Hi,
In the application I'm working on, we are using the Criteria API to formulate queries for our search screens. Everything works well, until we want to include a criterium on a property in a composite-element.
Our application needs to support multiple languages. Therefore, names of countries for example are localized, such that simple string values (like the country name) are replaced by an object that holds translations of that name for each culture that our application supports.
Since names of countries are translated in our app, the Name in Country is an association of type Translation.
This is the mapping for the Translation object. As you can see, a bag holding a collection of LocalizedString objects is defined. Since LocalizedString itself is an object, the composite-element tag is used in the definition.
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" default-access="property" assembly="NHibernateTestSolution.Business" namespace="NHibernateTestSolution.Business">
<class name="Translation" table="Translations">
<!-- Identity -->
<id name="Id" column="ID" type="Int32">
<generator class="native"/>
</id>
<property name="DefaultValue" column="DefaultValue" length="40"/>
<!-- Associations -->
<bag name="LocalizedStrings" table="LocalizedStrings" cascade="save-update">
<key column="TranslationID"/>
<composite-element class="LocalizedString">
<property name="Culture" column="Culture"/>
<property name="Value" column="Value"/>
</composite-element>
</bag>
</class>
</hibernate-mapping>
Here is the mapping for the Country object:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" default-access="property" assembly="NHibernateTestSolution.Business" namespace="NHibernateTestSolution.Business">
<class name="Country" table="Country">
<!-- Identity -->
<id name="Id" column="ID" type="Int32">
<generator class="native"/>
</id>
<!-- Associations -->
<many-to-one name="NameTranslation" class="Translation" column="Name" cascade="all-delete-orphan"/>
</class>
</hibernate-mapping>
The Translation object has a method GetTranslation(), which retrieves the right LocalizedString, based on the CurrentUICulture on the current thread ...
When applying the Criteria API, I need to be able to add a criterium that filters the Value property of the LocalizedString in the Countries taking into account the current culture.
This is where our problem is situated: how do I define a criterion that says something like Country.NameTranslation.LocalizedString.Value like 'xxx%'??? It seems to be a problem that the LocalizedStrings collection in Translation is defined as a bag of composite elements?
Defining an alias apparently is not supported for composite elements, and can only be defined on "real" associations?
While trying all sorts of approaches, I often get a QueryException saying that the NameTranslation.LocalizedStrings property can not be resolved.
I get the impression that to reach our goal, we will have to "go back" and use a HQL query concatenated as a string?
E.g.: this gives the required result, and works fine:
Code:
IQuery query = _session.CreateQuery("from Country c join c.NameTranslation t join t.LocalizedStrings l where l.Culture = 'en-US' and l.Value like :x");
Some help is really REALLY very welcome :). Thanx,
Serge