I had recently the need for using an id generator with two requirements:
I already knew about HiLo generator, and it seemed fine, except that the generated ids, on different sites, would most probably clash, unless I would setup a particular configuration leaving lots of room, and would constantly monitor its usage. So I decided to adapt it: I basically pick the generator produced by the HiLo generator, and add my own suffix to it, where the suffix is different for each site. Very simple, here it is:
public class CustomIdGenerator : TableHiLoGenerator
{
public const String NodeSuffixAppSettingsKey = "NodeSuffix";
protected static Int32 nodeSuffix = 0;
static CustomIdGenerator()
{
//try to read the node suffix from the application settings
if (Int32.TryParse(ConfigurationManager.AppSettings[NodeSuffixAppSettingsKey], out nodeSuffix) == false)
{
//the node suffix key does not exist or is not a number
throw new ApplicationException(String.Format("Application settings does not contain key {0} or it is not a number.", NodeSuffixAppSettingsKey));
}
}
public override Object Generate(ISessionImplementor session, Object obj)
{
//1 - get id using standard HiLo algorithm
Int64 baseId = (Int64) base.Generate(session, obj);
//2 - shift id to the left, leaving room for 3-digit node suffixes
baseId *= 1000;
//3 - combine id with the node suffix
baseId += nodeSuffix;
return (baseId);
}
}
It can be configured fluently:
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
this.Id(c => c.Id).Column("ID").GeneratedBy.Custom<CustomIdGenerator>();
this.Map(c => c.Name).Column("NAME").Not.Nullable();
this.Map(c => c.Address).Column("ADDRESS").Not.Nullable().LazyLoad();
this.HasMany<Order>(c => c.Orders).KeyColumn("CUSTOMERID").Inverse().AsSet().Cascade.All().Fetch.Join();
}
}
Or through .hbm.xml:
<class name="Customer" table="`CUSTOMER`"> <id name="Id" column="ID" type="long"> <generator class="CustomIdGenerator, CustomIdGeneratorAssembly"> </generator> </id>