facing issue while annotating below are both classes and Hbm.xml mentioned have tried different method but receiving exception - hibernate-mapping

**
Below are both the class Conversion below Hbm.xml file with annotation
facing issue while annotating have tried different method but receiving exception
**
public class Parent {
private Set<Childaction>childactions=new HashSet<>();
}
public class Childaction extends parent {
private Parent main;
}
<hibernate-mapping>
<set name="childactions" table = "child table" cascade="save-update">
<key column="ID1"foreign-key="Foreignkey1"/>
<many-to-many column="Execute_id" unique="true" class="Childaction"/>
</set>
<subclass name="Childaction" extends="Parent" discriminator-value="not null">
<join table="childtable" inverse="true" optional="true">
<key column="Execute_id" foreign-key="foreignkey2"/>
<many-to-one name="main" column="ID1"not-null="true"/>
</join>
</subclass>
<filter name="main"/>
</class>
</hibernate-mapping>

Related

NHibernate mapping not saving

I have the following Nhibernate XML file, edited to the core bits:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="TTP.DAO" namespace="TTP.DAO" xmlns="urn:nhibernate-mapping-2.2">
<class name="InitialProcessSetup" table="InitialProcessSetup" lazy="true" >
<id name="SetupID" column="setupID" unsaved-value="0" type="System.Int32">
<generator class="identity"/>
</id>
<property name="DateCreated" column="DateCreated" />
<many-to-one class="StoredUser" name="CreatedBy" column="CreatedBy" cascade="all-delete-orphan" not-null="true"/>
<property name="OriginalDeadline" column="Deadline" />
<property name="Detail" column="Detail" />
<bag name="Subjects" table="InitialProcessSetupRatingSubject" inverse="true" cascade="all-delete-orphan">
<key column="SetupId" not-null="true" />
<many-to-many column="SubjectStoredUserId" class="StoredUser" />
</bag>
<bag name="Reviewers" table="InitialProcessSetupReviewer" cascade="all-delete-orphan">
<key column="SetupId" not-null="true" />
<many-to-many column="ReviewerStoredUserId" class="StoredUser" />
</bag>
<bag name="Invitations" cascade="all-delete-orphan">
<key column="Setup" not-null="true"/>
<one-to-many class="ProcessInvitation" />
</bag>
</class>
I populate a new instance of the class indicated in the above mapping and save via GenericDAO().SaveOrUpdate(setup); and it saves the main object details but does not store the bit.
On the class Subjects is defined as a virtual property that returns IList-StoredUser. The class constructor sets this property to a new List-StoredUser-().
The table indicated by the Subjects bag element is a pure mapping table that is it has a SetupID and StoredUserID column and that's it.
I add using a StoredUser to my derived StoredUserDAO() to the Subjects lists before saving. After the call to SaveOrUpdate() I also call Flush() as well.
In my database (SQL Server 2008R2) The main setup data is saved and the stored user I added to the Subjects list property is also saved it's just the mapping table does not get the setupID/StoredUserID added.
I'm a bit of a noob with Nhibernate and this is an existing project.
Any help ideas on what is wrong would be most appreciated.
You have set inverse="true" for the Subjects collection. This implies that for NHibernate to create a record in the relation table, it must be the StoredUser that references the InitialProcessSetup.

NHibernate Mapping Exception: invalid child element

I'm having a problem with NHibernate and the mapping file when I try to save my drink object in my MVC application. My mapping file is an embedded resource and my hibernate.cfg.xml is copy always.
Here are my class.cs:
namespace FrancosPoS.DBMapping {
public class drink {
public drink() { }
public virtual int id { get; set; }
public virtual string type { get; set; }
public virtual string price { get; set; }
}
}
My XML mapping:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="FrancosPoS.DBMapping" namespace="FrancosPoS.DBMapping" xmlns="urn:nhibernate-mapping-2.2">
<class name="drink" table="drink" lazy="true" >
<id name="id">
<generator class="identity" />
<column name="id" sql-type="int(11)" not-null="true" />
</id>
<property name="type">
<column name="type" sql-type="varchar(25)" not-null="true" />
</property>
<property name="price">
<column name="price" sql-type="varchar(8)" not-null="true" />
</property>
</class>
</hibernate-mapping>
By the way, the connection opens and close fine if I don't try to save it on the database.
Here is my Solution Explorer:
Solution Explorer Image
And here is the error that is driving me nuts:
"Error: NHibernate.MappingException: FrancosPoS.DBMapping.drink.hbm.xml(6,8): XML validation error: The element 'id' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'column' in namespace 'urn:nhibernate-mapping-2.2'. ---> System.Xml.Schema.XmlSchemaValidationException: The element 'id' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'column' in namespace 'urn:nhibernate-mapping-2.2'.\r\n --- End of inner exception stack trace ---
the problem is in node id, it does not have a child, remove that node and it will simply be like this:
<id name="id">
<generator class="identity" />
</id>
the column's name is specified in id node, and you dont have to tell column has "not-null" constraint since id columns are always required
Also, in this line of your xml mapping:
<hibernate-mapping assembly="FrancosPoS.DBMapping" namespace="FrancosPoS.DBMapping" xmlns="urn:nhibernate-mapping-2.2">
"assembly" attribute seems to be wrong, it should be the name of your assembly (which i'm almost sure is "FrancosPos").

NHibernate - mapping the generic entity that implements the tree structure

I am relatively new to using Nhibernate but basic things already are working.
Now I have to map the generic entity that implements the tree structure. Separately, each one (only generic or only tree) works fine.
Here's the code for the model:
public class Test<T>
{
public virtual Int64 Id { get; set; }
public string Name { get; set; }
public IList<Test<T>> Children { get; set; }
}
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="PersistencyObjectModel" namespace="PersistencyObjectModel.Domain">
<class name="Test`1[String]">
<id name="Id">
<generator class="guid"/>
</id>
<property name="Name" length="50" not-null="true" unique="true"/>
<set name="Children" table="TEST_TEST_LINK" cascade="all-delete-orphan" >
<key column="ParentId"/>
<many-to-many column="ChildId" class="Test`1[String]"/>
</set>
</class>
</hibernate-mapping>
When I use that model, I get the following Nhibernate error:
{"persistent class PersistencyObjectModel.Domain.Test`1[[PersistencyObjectModel.Domain.String,
PersistencyObjectModel]], PersistencyObjectModel not found"}
What does this error mean and how can I fix it?
Update: try this
<hibernate-mapping namespace="PersistencyObjectModel.Domain"
assembly="PersistencyObjectModel"
xmlns="urn:nhibernate-mapping-2.2">
<class name="PersistencyObjectModel.Domain.Test`1[[System.String,
mscorlib, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
table="TestOfString">
<id name="Id">
<generator class="guid.comb"/>
</id>
<property name="Name" length="50" not-null="true" unique="true"/>
<set name="Children" table="TEST_TEST_LINK">
<key column="ParentId" />
<many-to-many column="ChildId"
class="PersistencyObjectModel.Domain.Test`1[[System.String,
mscorlib, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]]"/>
</set>
</class>
</hibernate-mapping>
Some things to note:
You can't use a guid generator with a long propery; change that to Guid
You must specify the name of the entity table
Use fully qualified names.

Hibernate collection loaded by custom SQL

I have some problems trying to get a bag collection of a class to be loaded through custom sql.
Here's the xml mappings I have for my class
<hibernate-mapping>
<class name="alekso.npe.model.Utente" table="VNPEZZ_UTE_MAT" lazy="false">
<id name="matricola" column="C_UTE_MAT">
</id>
<property name="nome" column="T_NOM" />
<property name="cognome" column="T_COG" />
<property name="email" column="T_EML" />
<bag name="ruoli" table="VNPEZX_UTE_APP_TRN"
inverse="false" lazy="true" fetch="select" cascade="all" >
<key column="C_UTE_MAT" />
<one-to-many class="alekso.npe.model.Ruolo" />
<loader query-ref="rolesQuery"/>
</bag>
</class>
<class name="alekso.npe.model.Ruolo" table="VNPEZH_TIP_USR"
lazy="false" where="C_APP = 'NPE'">
<id name="codice" column="C_TIP_USR">
</id>
<property name="nome" column="T_DES_TIP_USR"/>
</class>
<sql-query name="rolesQuery">
<return alias="role" class="alekso.npe.model.Ruolo"></return>
<load-collection alias="ruoli" role="alekso.npe.model.Ruolo" ></load-collection>
<![CDATA[select {ruolo.*}
from NPEA.vnpezx_ute_app_trn permesso join NPEA.vnpezh_tip_usr ruolo
on ruolo.c_tip_usr = permesso.c_tip_usr
where permesso.c_app = 'NPE'
and permesso.c_ute_mat = :matricola ]]>
</sql-query>
</hibernate-mapping>
But when I run the application I get an error:
org.hibernate.HibernateException: Errors in named queries: rolesQuery in the buildSessionFactory phase.
Can you tell me what's wrong with this mapping?
I tried both with and without the <return> tag inside the <sql-query> but it still don't work
I found out the error... the line <load-collection alias="ruoli" role="alekso.npe.model.Ruolo" ></load-collection> inside the custom query definition gives the error.
Without that line, everything works fine (almost... the collection of roles is lazy loaded even if I set lazy="false" everywhere).
But that line I removed is on the documentation, so I'd like to know why it's wrong.
I'll leave the question open for other to give some hints on this.

Why doesnt NHibernate eager fetch my data

I am using Nhibernate for my ORM.
I have a class "Control" that has a one to many relationship with ControlDetail (ie. A control has many controlDetails).
In the control xml config it has the following
<bag name="ControlDetails" lazy="true" access="property" order-by="SortOrder asc" cascade="all-delete-orphan"
table="ControlDetail">
<key column="ControlID"/>
<one-to-many class="ControlDetail"/>
</bag>
such that I believe unless otherwise told it would lazy load the controldetails of a control.
I am running NHProf to try and fix some performance issues we are having and it has identfied a Select N + 1 issue around these classes.
We are using a repository DA layer and I have tried to see if I can add in a way to eagerly fetch the data when required and came up with this.
public T GetById<T>(Int32 id, List<string> fetch) where T : BaseObject
{
T retObj = null;
ISession session = EnsureCurrentSession();
{
ICriteria criteria = session.CreateCriteria(typeof (T));
criteria.SetCacheable(true);
criteria.Add(Expression.Eq("Id", id));
foreach(var toFetch in fetch)
{
criteria.SetFetchMode(toFetch, FetchMode.Eager);
}
retObj = criteria.List<T>().FirstOrDefault();
}
return retObj;
}
*Note: I'm not a fan of how the repository is setup but it was done before I came to the project so we have to stick with this pattern for now.
I call this method like so
public Control GetByIDWithDetail(int controlID)
{
return DataRepository.Instance.GetById<Control>(controlID, new List<string>() {"ControlDetail"});
}
When I debug the GetByID method and look at the retObj I can see that the ControlDetails list has been populated (although strangely enough I also noticed without the setfetchmode set the list was being populated)
Even with this fix NHProf identifies a Select N+1 issue with the following line
List<ControlDetail> details = control.ControlDetails.ToList();
What exactly am I missing and how can I stop this N+1 but still iterate over the controlDetails list
EDIT: the xml configs look like so (slightly edited to make smaller)
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DomainObjects" assembly="DomainObjects">
<class name="Control" lazy="false" table="Control" optimistic-lock="version" select-before-update="true" >
<id name="Id" type="int" column="ControlID" access="property">
<generator class="native" />
</id>
<version name="Version" column="Version" />
<property name="AdministrativeControl" column="AdministrativeControl" access="property" not-null="true" />
<property name="Description" column="ControlDescription" access="property" />
<property name="Title" column="Title" access="property" />
<property name="CountOfChildControls" access="property" formula="(select count(*) from Control where Control.ParentControlID = ControlID)" />
<bag name="ControlDetails" lazy="true" access="property" order-by="SortOrder asc" cascade="all-delete-orphan"
table="ControlDetail">
<key column="ControlID" />
<one-to-many class="ControlDetail" />
</bag>
</class>
</hibernate-mapping>
and this
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DomainObjects" assembly="DomainObjects">
<class name="ControlDetail" lazy="false" table="ControlDetail" select-before-update="true" optimistic-lock="version">
<id name="Id" type="int" column="ControlDetailID" access="property">
<generator class="native" />
</id>
<version name="Version" column="Version" />
<property name="Description" column="Description" access="property" not-null="true" />
<property name="Title" column="Title" access="property" />
<many-to-one name="Control" lazy="false" class="Control" column="ControlID" access="property"/>
</class>
</hibernate-mapping>
There is a substantial difference between eager fetching and eager loading. Fetching means: putting into the same query. It has several side effects and may break it. Eager loading means forcing NH to load it immediately, not waiting until it is accessed the first time. It is still loaded using additional queries, which leads to the N+1 problem.
NH probably does not eagerly fetch because the property is called ControlDetails, but you pass ControlDetail as argument.
On the other side, this isn't a good way to avoid the N+1 problem. Use batch-size instead. It is fully transparent to the application and reduces the amount of queries by the given factor (values from 5 to 50 make sense, use 10 if you don't know what to use).
One option, you can reduce the select n+1 problem, keep lazy loading and forget about eager loading....
All you need to do is to add one simple attribute batch-size to your XML
<bag name="ControlDetails" batch-size="25" ..>
I also noticed that you have lazy="true" in your mapping, did you try changing to false?