Skip to content

Commit 6242b62

Browse files
XML mapping improvement: Adds support for a 'generator' attribute on <id> (NH-1007)
1 parent 90cdaab commit 6242b62

File tree

7 files changed

+197
-30
lines changed

7 files changed

+197
-30
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH1007
4+
{
5+
public class Employer1
6+
{
7+
public virtual Guid Id { get; set; }
8+
public virtual string Name { get; set; }
9+
}
10+
11+
public class Employer2
12+
{
13+
public virtual Guid Id { get; set; }
14+
public virtual string Name { get; set; }
15+
}
16+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System;
2+
using NHibernate.Cfg;
3+
using NHibernate.Cfg.MappingSchema;
4+
using NHibernate.Cfg.XmlHbmBinding;
5+
using NHibernate.Dialect;
6+
using NHibernate.Mapping;
7+
using NUnit.Framework;
8+
9+
namespace NHibernate.Test.NHSpecificTest.NH1007
10+
{
11+
[TestFixture]
12+
public class Fixture : BugTestCase
13+
{
14+
[Test]
15+
public void TestIdGeneratorAttributeMappingOnIdentifier()
16+
{
17+
using (ISession session = base.OpenSession())
18+
using (ITransaction transaction = session.BeginTransaction())
19+
{
20+
var employer = new Employer1();
21+
22+
Assert.That(employer.Id, Is.EqualTo(Guid.Empty));
23+
24+
session.Save(employer);
25+
26+
Assert.That(employer.Id, Is.Not.EqualTo(Guid.Empty));
27+
28+
transaction.Commit();
29+
}
30+
}
31+
32+
[Test]
33+
public void MappingIdGeneratorWithAttributeTakesPrecendenceOverMappingWithElement()
34+
{
35+
using (ISession session = base.OpenSession())
36+
using (ITransaction transaction = session.BeginTransaction())
37+
{
38+
var employer = new Employer2();
39+
40+
Assert.That(employer.Id, Is.EqualTo(Guid.Empty));
41+
42+
session.Save(employer);
43+
44+
Assert.That(employer.Id, Is.Not.EqualTo(Guid.Empty));
45+
46+
transaction.Commit();
47+
}
48+
}
49+
50+
[Test]
51+
public void ConfiguringIdGeneratorUsingAttributeAndElementIsEquivalent()
52+
{
53+
// <id name="Employer1"><generator class="guid" /></id>
54+
var mapIdentityGeneratorByElement = new HbmMapping()
55+
{
56+
Items = new object[]
57+
{
58+
new HbmClass()
59+
{
60+
name = "Employer1",
61+
Item = new HbmId() { name = "Id", generator1 = "guid" },
62+
Items = new object[] {new HbmProperty() {name = "Name"}}
63+
}
64+
}
65+
};
66+
67+
// <id name="Employer1" generator="guid" />
68+
var mapIdentityGeneratorByAttribute = new HbmMapping()
69+
{
70+
Items = new object[]
71+
{
72+
new HbmClass()
73+
{
74+
name = "Employer1",
75+
Item = new HbmId() { name = "Id", generator = new HbmGenerator() { @class = "guid" } },
76+
Items = new object[] {new HbmProperty() {name = "Name"}}
77+
}
78+
}
79+
};
80+
81+
VerifyMapping(mapIdentityGeneratorByElement);
82+
VerifyMapping(mapIdentityGeneratorByAttribute);
83+
}
84+
85+
private void VerifyMapping(HbmMapping mapping)
86+
{
87+
var dialect = new MsSql2008Dialect();
88+
var configuration = new Configuration();
89+
var mappings = configuration.CreateMappings(dialect);
90+
mappings.DefaultAssembly = "NHibernate.Test";
91+
mappings.DefaultNamespace = "NHibernate.Test.NHSpecificTest.NH1007";
92+
93+
var rootBinder = new MappingRootBinder(mappings, dialect);
94+
rootBinder.Bind(mapping);
95+
96+
var employer = rootBinder.Mappings.GetClass("NHibernate.Test.NHSpecificTest.NH1007.Employer1");
97+
var simpleValue = employer.Identifier as SimpleValue;
98+
if (simpleValue != null)
99+
{
100+
Assert.That(simpleValue.IdentifierGeneratorStrategy, Is.EqualTo("guid"));
101+
Assert.That(simpleValue.IdentifierGeneratorProperties, Is.Empty);
102+
}
103+
}
104+
105+
protected override void OnTearDown()
106+
{
107+
using (ISession session = base.OpenSession())
108+
using (ITransaction transaction = session.BeginTransaction())
109+
{
110+
session.CreateQuery("delete from System.Object").ExecuteUpdate();
111+
transaction.Commit();
112+
}
113+
}
114+
}
115+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHibernate.Test.NHSpecificTest.NH1007" assembly="NHibernate.Test">
3+
4+
<class name="Employer1">
5+
<id name="Id" generator="guid" />
6+
<property name="Name" />
7+
</class>
8+
9+
<!--
10+
Mapping to demonstrate that the 'column' attribute takes precedence over a 'column' element - and, for consistency,
11+
the same behaviour applies to the generator attribute/element
12+
-->
13+
<class name="Employer2">
14+
<id name="Id" generator="guid">
15+
<generator class="invalid_generator_class" />
16+
</id>
17+
18+
<property name="Name" column="Name">
19+
<column name="InvalidColumnName" />
20+
</property>
21+
</class>
22+
23+
</hibernate-mapping>

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,8 @@
650650
<Compile Include="NHSpecificTest\Futures\LinqFutureFixture.cs" />
651651
<Compile Include="NHSpecificTest\NH0000\Entity.cs" />
652652
<Compile Include="NHSpecificTest\NH0000\Fixture.cs" />
653+
<Compile Include="NHSpecificTest\NH1007\Employer.cs" />
654+
<Compile Include="NHSpecificTest\NH1007\Fixture.cs" />
653655
<Compile Include="NHSpecificTest\NH1136\Address.cs" />
654656
<Compile Include="NHSpecificTest\NH1136\FeeMatrixType.cs" />
655657
<Compile Include="NHSpecificTest\NH1136\Fixture.cs" />
@@ -2749,6 +2751,7 @@
27492751
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
27502752
</ItemGroup>
27512753
<ItemGroup>
2754+
<EmbeddedResource Include="NHSpecificTest\NH1007\Mappings.hbm.xml" />
27522755
<EmbeddedResource Include="NHSpecificTest\NH2869\Mappings.hbm.xml" />
27532756
<EmbeddedResource Include="NHSpecificTest\NH0000\Mappings.hbm.xml" />
27542757
<EmbeddedResource Include="NHSpecificTest\NH2828\Mappings.hbm.xml" />

src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,6 +2096,10 @@ public partial class HbmId {
20962096
/// <remarks/>
20972097
[System.Xml.Serialization.XmlAttributeAttribute("unsaved-value")]
20982098
public string unsavedvalue;
2099+
2100+
/// <remarks/>
2101+
[System.Xml.Serialization.XmlAttributeAttribute("generator")]
2102+
public string generator1;
20992103
}
21002104

21012105
/// <remarks/>
Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
using System;
22
using NHibernate.Cfg.MappingSchema;
33
using NHibernate.Mapping;
4+
using NHibernate.Type;
45

56
namespace NHibernate.Cfg.XmlHbmBinding
67
{
78
public class ClassIdBinder : ClassBinder
89
{
9-
public ClassIdBinder(ClassBinder parent)
10-
: base(parent)
11-
{
12-
}
10+
public ClassIdBinder(ClassBinder parent) : base(parent) { }
1311

1412
public void BindId(HbmId idSchema, PersistentClass rootClass, Table table)
1513
{
@@ -21,16 +19,20 @@ public void BindId(HbmId idSchema, PersistentClass rootClass, Table table)
2119
rootClass.Identifier = id;
2220

2321
Func<HbmColumn> defaultColumn = () => new HbmColumn
24-
{
25-
name = idSchema.name ?? RootClass.DefaultIdentifierColumnName,
26-
length = idSchema.length
27-
};
22+
{
23+
name = idSchema.name ?? RootClass.DefaultIdentifierColumnName,
24+
length = idSchema.length
25+
};
26+
2827
new ColumnsBinder(id, Mappings).Bind(idSchema.Columns, false, defaultColumn);
2928

3029
CreateIdentifierProperty(idSchema, rootClass, id);
31-
VerifiyIdTypeIsValid(id, rootClass.EntityName);
32-
new IdGeneratorBinder(Mappings).BindGenerator(id, idSchema.generator);
30+
VerifiyIdTypeIsValid(id.Type, rootClass.EntityName);
31+
32+
new IdGeneratorBinder(Mappings).BindGenerator(id, GetIdGenerator(idSchema));
33+
3334
id.Table.SetIdentifierValue(id);
35+
3436
BindUnsavedValue(idSchema, id);
3537
}
3638
}
@@ -40,10 +42,9 @@ private void CreateIdentifierProperty(HbmId idSchema, PersistentClass rootClass,
4042
if (idSchema.name != null)
4143
{
4244
string access = idSchema.access ?? mappings.DefaultAccess;
43-
id.SetTypeUsingReflection(rootClass.MappedClass == null ? null : rootClass.MappedClass.AssemblyQualifiedName,
44-
idSchema.name, access);
45+
id.SetTypeUsingReflection(rootClass.MappedClass == null ? null : rootClass.MappedClass.AssemblyQualifiedName, idSchema.name, access);
4546

46-
var property = new Property(id) {Name = idSchema.name};
47+
var property = new Property(id) { Name = idSchema.name };
4748

4849
if (property.Value.Type == null)
4950
throw new MappingException("could not determine a property type for: " + property.Name);
@@ -62,19 +63,23 @@ private void CreateIdentifierProperty(HbmId idSchema, PersistentClass rootClass,
6263
}
6364
}
6465

65-
private static void VerifiyIdTypeIsValid(IValue id, string className)
66+
private HbmGenerator GetIdGenerator(HbmId idSchema)
67+
{
68+
return String.IsNullOrEmpty(idSchema.generator1) ? idSchema.generator : new HbmGenerator() { @class = idSchema.generator1 };
69+
}
70+
71+
private static void VerifiyIdTypeIsValid(IType idType, string className)
6672
{
67-
if (id.Type == null)
73+
if (idType == null)
6874
throw new MappingException(string.Format("Must specify an identifier type: {0}.", className));
6975

70-
if (id.Type.ReturnedClass.IsArray)
71-
throw new MappingException(
72-
"Illegal use of an array as an identifier (arrays don't reimplement equals).");
76+
if (idType.ReturnedClass.IsArray)
77+
throw new MappingException("Illegal use of an array as an identifier (arrays don't reimplement equals).");
7378
}
7479

7580
private static void BindUnsavedValue(HbmId idSchema, SimpleValue id)
7681
{
7782
id.NullValue = idSchema.unsavedvalue ?? (id.IdentifierGeneratorStrategy == "assigned" ? "undefined" : null);
7883
}
7984
}
80-
}
85+
}

src/NHibernate/nhibernate-mapping.xsd

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184
<xs:attribute name="proxy" type="xs:string" />
185185
<xs:attribute name="lazy" type="xs:boolean">
186186
</xs:attribute>
187-
<xs:attribute name="schema-action" type="xs:string" />
187+
<xs:attribute name="schema-action" type="xs:string" />
188188
<xs:attribute name="table" type="xs:string" />
189189
<xs:attribute name="schema" type="xs:string" />
190190
<xs:attribute name="catalog" type="xs:string" />
@@ -468,7 +468,7 @@
468468
</xs:choice>
469469
<xs:attribute name="name" use="required" type="xs:string" />
470470
<xs:attribute name="condition" type="xs:string" />
471-
<xs:attribute name="use-many-to-one" default="true" type="xs:boolean"/>
471+
<xs:attribute name="use-many-to-one" default="true" type="xs:boolean"/>
472472
</xs:complexType>
473473
</xs:element>
474474
<xs:element name="filter-param">
@@ -544,6 +544,7 @@
544544
<xs:attribute name="type" type="xs:string" />
545545
<xs:attribute name="length" type="xs:positiveInteger" />
546546
<xs:attribute name="unsaved-value" type="xs:string" />
547+
<xs:attribute name="generator" type="xs:string" />
547548
</xs:complexType>
548549
</xs:element>
549550
<xs:element name="idbag">
@@ -692,8 +693,8 @@
692693
<xs:attribute name="name" type="xs:string" />
693694
<xs:attribute name="proxy" type="xs:string" />
694695
<xs:attribute name="table" type="xs:string" />
695-
<xs:attribute name="schema-action" type="xs:string" />
696-
<xs:attribute name="schema" type="xs:string" />
696+
<xs:attribute name="schema-action" type="xs:string" />
697+
<xs:attribute name="schema" type="xs:string" />
697698
<xs:attribute name="catalog" type="xs:string" />
698699
<xs:attribute name="subselect" type="xs:string" />
699700
<xs:attribute name="dynamic-update" default="false" type="xs:boolean">
@@ -866,11 +867,11 @@
866867
<xs:complexType>
867868
<xs:sequence>
868869
<xs:element ref="meta" minOccurs="0" maxOccurs="unbounded" />
869-
<xs:choice minOccurs="0" maxOccurs="unbounded">
870-
<xs:element ref="column" />
871-
<xs:element ref="formula" />
872-
</xs:choice>
873-
</xs:sequence>
870+
<xs:choice minOccurs="0" maxOccurs="unbounded">
871+
<xs:element ref="column" />
872+
<xs:element ref="formula" />
873+
</xs:choice>
874+
</xs:sequence>
874875
<xs:attribute name="name" use="required" type="xs:string" />
875876
<xs:attribute name="access" type="xs:string" />
876877
<xs:attribute name="class" type="xs:string" />
@@ -1061,8 +1062,8 @@
10611062
<xs:element name="parent">
10621063
<xs:complexType>
10631064
<xs:attribute name="name" use="required" type="xs:string" />
1064-
<xs:attribute name="access" type="xs:string" />
1065-
</xs:complexType>
1065+
<xs:attribute name="access" type="xs:string" />
1066+
</xs:complexType>
10661067
</xs:element>
10671068
<xs:element name="primitive-array">
10681069
<xs:complexType>

0 commit comments

Comments
 (0)