diff --git a/src/NHibernate.Test/NHSpecificTest/GH3607/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH3607/FixtureByCode.cs
new file mode 100644
index 00000000000..0ce9b1a592c
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3607/FixtureByCode.cs
@@ -0,0 +1,31 @@
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3607
+{
+ ///
+ /// By code mapping serialization failure since v5.4.1. Adapted from .
+ ///
+ [TestFixture]
+ public class FixtureByCode : TestCaseMappingByCode
+ {
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.AddMappings(new[] { typeof(OrderMapping), typeof(LineItemMapping), typeof(LineItemDataMapping) });
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ [Test]
+ public void SerializeMappingToXml()
+ {
+ var mapping = GetMappings();
+ string serialized = "";
+ Assert.That(() => serialized = mapping.AsString(), Throws.Nothing, "Mapping serialization failure");
+ var config = new Configuration();
+ Assert.That(() => config.AddXml(serialized), Throws.Nothing, "Configuration with serialized mapping has failed");
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3607/LineItem.cs b/src/NHibernate.Test/NHSpecificTest/GH3607/LineItem.cs
new file mode 100644
index 00000000000..146a7407b26
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3607/LineItem.cs
@@ -0,0 +1,15 @@
+namespace NHibernate.Test.NHSpecificTest.GH3607
+{
+ public class LineItem
+ {
+ public virtual int Id { get; set; }
+
+ public virtual Order ParentOrder { get; set; }
+
+ public virtual string ItemName { get; set; }
+
+ public virtual decimal Amount { get; set; }
+
+ public virtual LineItemData Data { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemData.cs b/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemData.cs
new file mode 100644
index 00000000000..5bcfa3ad64c
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemData.cs
@@ -0,0 +1,9 @@
+namespace NHibernate.Test.NHSpecificTest.GH3607
+{
+ public class LineItemData
+ {
+ public virtual LineItem LineItem { get; set; }
+
+ public virtual string Data { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemDataMapping.cs b/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemDataMapping.cs
new file mode 100644
index 00000000000..66634421a3b
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemDataMapping.cs
@@ -0,0 +1,14 @@
+using NHibernate.Mapping.ByCode.Conformist;
+
+namespace NHibernate.Test.NHSpecificTest.GH3607
+{
+ public class LineItemDataMapping : ClassMapping
+ {
+ public LineItemDataMapping()
+ {
+ OneToOne(x => x.LineItem, m => m.Constrained(true));
+
+ Property(x => x.Data);
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemMapping.cs b/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemMapping.cs
new file mode 100644
index 00000000000..3918b0a84f3
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3607/LineItemMapping.cs
@@ -0,0 +1,21 @@
+using NHibernate.Mapping.ByCode;
+using NHibernate.Mapping.ByCode.Conformist;
+
+namespace NHibernate.Test.NHSpecificTest.GH3607
+{
+ public class LineItemMapping : ClassMapping
+ {
+ public LineItemMapping()
+ {
+ Id(x => x.Id, m => m.Generator(new IdentityGeneratorDef()));
+
+ Property(x => x.ItemName);
+
+ Property(x => x.Amount);
+
+ ManyToOne(x => x.ParentOrder);
+
+ ManyToOne(x => x.Data);
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3607/Order.cs b/src/NHibernate.Test/NHSpecificTest/GH3607/Order.cs
new file mode 100644
index 00000000000..be3b9d05ffc
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3607/Order.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+
+namespace NHibernate.Test.NHSpecificTest.GH3607
+{
+ public class Order
+ {
+ public virtual int Id { get; set; }
+
+ public virtual DateTime CreatedDate { get; set; }
+
+ public virtual ISet Items { get; protected set; } = new HashSet();
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3607/OrderMapping.cs b/src/NHibernate.Test/NHSpecificTest/GH3607/OrderMapping.cs
new file mode 100644
index 00000000000..036c65e47a5
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3607/OrderMapping.cs
@@ -0,0 +1,22 @@
+using NHibernate.Mapping.ByCode;
+using NHibernate.Mapping.ByCode.Conformist;
+
+namespace NHibernate.Test.NHSpecificTest.GH3607
+{
+ public class OrderMapping : ClassMapping
+ {
+ public OrderMapping()
+ {
+ Table("`Order`");
+ Id(x => x.Id, m => m.Generator(new IdentityGeneratorDef()));
+
+ Property(x => x.CreatedDate);
+
+ Set(x => x.Items, m =>
+ {
+ m.Inverse(true);
+ m.OptimisticLock(true);
+ }, a => a.OneToMany());
+ }
+ }
+}
diff --git a/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs b/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs
index e0740e17937..aec82a44ee4 100644
--- a/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs
+++ b/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs
@@ -18,9 +18,13 @@ public string Access
get { return access; }
}
+ // 6.0 Todo : remove XmlIgnore after removing the setter. See #3607 fix.
+ [XmlIgnore]
public bool OptimisticLock
{
get => optimisticlock;
+ // Since v5.4.10
+ [Obsolete("Providing a setter for OptimisticLock was unintended and will be removed.")]
set => optimisticlock = value;
}