Continuing with our series of comparisons between NHibernate and MyBatis.NET, we will be looking at how to actually persist our data. We will build on the code we have developed in both this series and the original MyBatis.NET one, which can be found here and here.
The first part of this comparison will cover the NHibernate way. The second part will cover the MyBatis.NET way.
The NHibernate Way
We’ll start with NHibernate; recall our simple Employee class.
We want to be able to persist changes, as well as new employees. Let’s wire up a simple test for the first case.
[Test]
public void CanPersistChangesToExistingEmployeeTest()
{
Employee e = PersonRepo.GetEmployeeById(1);
int originalHours = e.VacationHours;
e.VacationHours = originalHours + 1;
PersonRepo.SaveEmployee(e);
Employee e2 = PersonRepo.GetEmployeeById(1);
Assert.That(e2.VacationHours, Is.EqualTo(originalHours + 1));
}
The SaveEmployee method is new. Implementing it is a breeze.
public static void SaveEmployee(Employee e)
{
using (ISession s = AWHelper.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
s.SaveOrUpdate(e);
tx.Commit();
}
}
And with that, our test passes. A slightly more interesting question is whether or not the same code can save out changes to the employee’s address.
[Test]
public void CanPersistChangesToExistingEmployeeAddressTest()
{
string newCityName = "booyeah";
Employee e = PersonRepo.GetEmployeeById(1);
e.Addresses[0].City = newCityName;
PersonRepo.SaveEmployee(e);
Employee e2 = PersonRepo.GetEmployeeById(1);
Assert.That(e.Addresses[0].City, Is.EqualTo(newCityName));
}
And the answer is yes, this test passes right away. So with a bit more code, NHibernate knows how to save our entity simply from the information that it has in the mapping.
Now for creating a new entity, another test.
[Test]
public void CanPersistNewEmployeeTest()
{
Employee e = new Employee();
e.VacationHours = 4;
e.CurrentMaritalStatus = MaritalStatus.Married;
PersonRepo.SaveEmployee(e);
Employee e2 = PersonRepo.GetEmployeeById(e.Id);
Assert.That(e2, Is.SameAs(e));
}
Running this test fails with the below error message.
To fix this, we have to tell NHibernate that the Id column is an identity column by changing the Employee mapping a bit.
<class name="NHAdventureWorksDAL.Person.Employee,NHAdventureWorksDAL"
table="HumanResources.Employee">
<id name="Id" column="EmployeeId">
<generator class="identity" />
</id>
<property name="VacationHours" />
<property name="CurrentMaritalStatus"
column="MaritalStatus"
type="NHAdventureWorksDAL.Helpers.MaritalStatusHandler,NHAdventureWorksDAL" />
<bag name="Addresses"
table="HumanResources.EmployeeAddress"
lazy="false">
<key column="EmployeeID" />
<many-to-many class="NHAdventureWorksDAL.Address,NHAdventureWorksDAL"
column="AddressID" />
</bag>
</class>
The addition that fixes our issue is the addition of the generator tag within the id tag. This tells NHibernate that our id is an identity column and should be handled as such. When we re-run the test we get another error however.
So now we have to define, minimally, all non-null columns in both our mapping and our entity. Our new class diagram appears below.
And our new mapping appears below.
<class name="NHAdventureWorksDAL.Person.Employee,NHAdventureWorksDAL"
table="HumanResources.Employee">
<id name="Id" column="EmployeeId">
<generator class="identity" />
</id>
<property name="VacationHours" />
<property name="NationalIDNumber" />
<property name="ContactID" />
<property name="LoginID" />
<property name="Title" />
<property name="BirthDate" />
<property name="Gender" />
<property name="HireDate" />
<property name="Salaried" column="SalariedFlag" />
<property name="SickLeaveHours" />
<property name="Current" column="CurrentFlag" />
<property name="rowguid" />
<property name="ModifiedDate" />
<property name="CurrentMaritalStatus"
column="MaritalStatus"
type="NHAdventureWorksDAL.Helpers.MaritalStatusHandler,NHAdventureWorksDAL" />
<bag name="Addresses"
table="HumanResources.EmployeeAddress"
lazy="false">
<key column="EmployeeID" />
<many-to-many class="NHAdventureWorksDAL.Address,NHAdventureWorksDAL"
column="AddressID" />
</bag>
</class>
Finally, we modify our test to populate the new non-null properties, along with some gimmicks so that we can run the test more than once without violating the unique constraints on the login id and national id number columns.
[Test]
public void CanPersistNewEmployeeTest()
{
Employee e = new Employee
{
VacationHours = 4,
CurrentMaritalStatus = MaritalStatus.Married,
ContactID = 1,
BirthDate = DateTime.Now.AddYears(-40),
Current = true,
Gender = "M",
HireDate = DateTime.Now,
LoginID = Guid.NewGuid().ToString(),
ModifiedDate = DateTime.Now,
NationalIDNumber = Guid.NewGuid().ToString().Substring(0,10),
rowguid = Guid.NewGuid(),
Salaried = true,
SickLeaveHours = 0,
Title = "Oh Yeah"
};
PersonRepo.SaveEmployee(e);
Employee e2 = PersonRepo.GetEmployeeById(e.Id);
Assert.That(e2.Title, Is.EqualTo(e.Title));
Assert.That(e2.LoginID, Is.EqualTo(e.LoginID));
Assert.That(e2.Id, Is.EqualTo(e.Id));
Assert.That(e2.NationalIDNumber, Is.EqualTo(e.NationalIDNumber));
}
And with that, our test passes.
In the next (sub) part of this, we will explore how to accomplish this same thing using MyBatis.NET.
[...] This post was mentioned on Twitter by Proggit Articles, Jeff Vera. Jeff Vera said: Blogged: NHibernate vs. MyBatis.NET – Saving Entities, Part 1 http://bit.ly/9vyaMK [...]
NHibernate vs. MyBatis.NET – Saving Entities…
Thank you for submitting this cool story – Trackback from DotNetShoutout…