This is part two in the series describing how to write a 'legacy'/'migrating' hbm for backward compatibility.
The refactoring in this post is the splitting of a class 'Bridge'. See the class diagram:
Originally there was one big Bridge class, but later it was decided to split it into a Bridge and a BridgeDefinition. Also the properties don't exactly match:
- SideArea: no longer exists
- Pillars -> renamed to NumPillars
- Color: should always be 'RED'
- IsOpen: new
Here are the old HBM (for reference) and the new HBM:
Section | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||
|
We need to tackle four property changes and the class split itself. Let's start with the property changes:
Property | Change | Solution | ||
---|---|---|---|---|
SideArea | No longer exists | Do nothing! | ||
Pillars | Renamed to NumPillars |
| ||
Color | Should always be 'RED' when loading old data |
| ||
IsOpen | New property, should always be 'true' when loading old data |
|
Finally we need to tackle how to split the class. Fortunately NHibernate has something called components, where it persists two classes into one table. We just tell NHibernate to threat the table as such a table, with BridgeDefinition being a 'component' of Bridge and NHibernate will load the single table into two entities, just like we want. The resulting HBM looks like this:
Code Block | ||
---|---|---|
| ||
<class name="Bridge"> <id name="Id"> <generator class="guid" /> </id> <property name="Name" /> <property name="Color" formula="'RED'"/> <property name="HasRoad"/> <property name="IsOpen" formula="1"/> <component name="Definition" class="BridgeDefinition"> <property name="Type"/> <property name="Width"/> <property name="Height"/> <property name="NumPillars" formula="Pillars"/> </component> </class> |
Note that the Id property of the BridgeDefinition component is not mapped. However when saving this class in the new session (with the new hbm's), it will receive an Id anyway.
The resulting SQL:
No Format |
---|
SELECT bridge.Id, bridge.Name, bridge.HasRoad, bridge.Type, bridge.Width, bridge.Height, 'RED', 1, bridge.Pillars FROM Bridge bridge WHERE bridge.Id=... |
Note that the splitting into a component is handled by NHibernate in code and has no effect on the SQL.
Hopefully this post shows that what appears to be a more difficult refactoring, turns out to be pretty easily mapped. See previous post for SVN link to source code. Next up: class merge.