diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3539/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3539/Fixture.cs
new file mode 100644
index 0000000000..342d688f1c
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3539/Fixture.cs
@@ -0,0 +1,85 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by AsyncGenerator.
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+
+using NHibernate.Cfg;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3539
+{
+	using System.Threading.Tasks;
+	[TestFixture]
+	public class FixtureAsync : BugTestCase
+	{
+		protected override void Configure(Configuration configuration)
+		{
+			configuration.SetProperty(Cfg.Environment.GenerateStatistics, "true");
+		}
+
+		protected override void OnTearDown()
+		{
+			using (var s = Sfi.OpenSession())
+			using (var t = s.BeginTransaction())
+			{
+				s.Delete("from Person");
+				t.Commit();
+			}
+
+			base.OnTearDown();
+		}
+
+		[Test]
+		public async Task TestComponentAsync()
+		{
+			int personId;
+			using (var s = Sfi.OpenSession())
+			using (var t = s.BeginTransaction())
+			{
+				var person = new Person(age: 20)
+				{
+					CardInfo = new("card1", "card2")
+				};
+				await (s.SaveAsync(person));
+				await (t.CommitAsync());
+				await (s.FlushAsync());
+				personId = person.Id;
+			}
+
+			using (var s = Sfi.OpenSession())
+			using (var t = s.BeginTransaction())
+			{
+				var restored = await (s.GetAsync<Person>(personId));
+
+				var oldCardInfo = restored.CardInfo;
+
+				Assert.That(oldCardInfo.GetCardsCopy().Contains("card1"));
+				Assert.That(oldCardInfo.GetCardsCopy().Contains("card2"));
+
+				var newCardInfo = new CardInfo("card1", "card2");
+
+				Assert.That(oldCardInfo.GetHashCode(), Is.EqualTo(newCardInfo.GetHashCode()));
+				Assert.That(oldCardInfo.Equals(newCardInfo));
+
+				restored.CardInfo = newCardInfo;
+
+				// Expected behaviour:
+				//
+				// At this point there should be no DML statements because newCardInfo
+				// is the same as the old one. But NHibernate will generate DELETE
+				// followed by 2 INSERT into OldCards table.
+
+				using (var x = new SqlLogSpy())
+				{
+					await (t.CommitAsync());
+					Assert.That(x.GetWholeLog(), Is.Empty);
+				}
+			}
+		}
+	}
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3539/CardInfo.cs b/src/NHibernate.Test/NHSpecificTest/GH3539/CardInfo.cs
new file mode 100644
index 0000000000..9596e2b61e
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3539/CardInfo.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace NHibernate.Test.NHSpecificTest.GH3539;
+
+public class CardInfo
+{
+	private readonly ISet<string> _oldCards;
+
+	protected CardInfo() { }
+
+	public CardInfo(params string[] cards)
+	{
+		_oldCards = cards.ToHashSet();
+	}
+
+	public virtual ISet<string> GetCardsCopy()
+	{
+		return _oldCards.ToHashSet();
+	}
+
+	public override bool Equals(object obj)
+	{
+		if (obj is null)
+		{
+			return false;
+		}
+		if (ReferenceEquals(this, obj))
+		{
+			return true;
+		}
+		if (obj.GetType() != GetType())
+		{
+			return false;
+		}
+		var other = (CardInfo) obj;
+		return _oldCards.SetEquals(other._oldCards);
+	}
+
+	public override int GetHashCode()
+	{
+		var hashCode = new HashCode();
+		foreach (var card in _oldCards) hashCode.Add(card);
+		return hashCode.ToHashCode();
+	}
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3539/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH3539/Fixture.cs
new file mode 100644
index 0000000000..2311b2e50e
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3539/Fixture.cs
@@ -0,0 +1,74 @@
+using NHibernate.Cfg;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3539
+{
+	[TestFixture]
+	public class Fixture : BugTestCase
+	{
+		protected override void Configure(Configuration configuration)
+		{
+			configuration.SetProperty(Cfg.Environment.GenerateStatistics, "true");
+		}
+
+		protected override void OnTearDown()
+		{
+			using (var s = Sfi.OpenSession())
+			using (var t = s.BeginTransaction())
+			{
+				s.Delete("from Person");
+				t.Commit();
+			}
+
+			base.OnTearDown();
+		}
+
+		[Test]
+		public void TestComponent()
+		{
+			int personId;
+			using (var s = Sfi.OpenSession())
+			using (var t = s.BeginTransaction())
+			{
+				var person = new Person(age: 20)
+				{
+					CardInfo = new("card1", "card2")
+				};
+				s.Save(person);
+				t.Commit();
+				s.Flush();
+				personId = person.Id;
+			}
+
+			using (var s = Sfi.OpenSession())
+			using (var t = s.BeginTransaction())
+			{
+				var restored = s.Get<Person>(personId);
+
+				var oldCardInfo = restored.CardInfo;
+
+				Assert.That(oldCardInfo.GetCardsCopy().Contains("card1"));
+				Assert.That(oldCardInfo.GetCardsCopy().Contains("card2"));
+
+				var newCardInfo = new CardInfo("card1", "card2");
+
+				Assert.That(oldCardInfo.GetHashCode(), Is.EqualTo(newCardInfo.GetHashCode()));
+				Assert.That(oldCardInfo.Equals(newCardInfo));
+
+				restored.CardInfo = newCardInfo;
+
+				// Expected behaviour:
+				//
+				// At this point there should be no DML statements because newCardInfo
+				// is the same as the old one. But NHibernate will generate DELETE
+				// followed by 2 INSERT into OldCards table.
+
+				using (var x = new SqlLogSpy())
+				{
+					t.Commit();
+					Assert.That(x.GetWholeLog(), Is.Empty);
+				}
+			}
+		}
+	}
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3539/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/GH3539/Mappings.hbm.xml
new file mode 100644
index 0000000000..a153459cc0
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3539/Mappings.hbm.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping 
+	xmlns="urn:nhibernate-mapping-2.2" 
+	assembly="NHibernate.Test" 
+	namespace="NHibernate.Test.NHSpecificTest.GH3539">
+
+	<class name="Person" table="People">
+		<id name="_id" type="int" column="ID" access="field">
+			<generator class="increment"/>
+		</id>
+    <property name="_age" type="int" access="field"/>
+    
+    <component name="_cardInfo" access="field">
+      <set name="_oldCards" table="OldCards" cascade="all" access="field" >
+        <key column="PersonId" />
+        <element column="Card" type="String" />
+      </set>
+    </component>
+	</class>
+
+</hibernate-mapping>
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3539/Person.cs b/src/NHibernate.Test/NHSpecificTest/GH3539/Person.cs
new file mode 100644
index 0000000000..ce4fe44848
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3539/Person.cs
@@ -0,0 +1,35 @@
+namespace NHibernate.Test.NHSpecificTest.GH3539
+{
+	public class Person
+	{
+		private int _id;
+		private int _age;
+		private CardInfo _cardInfo;
+
+		protected Person() { }
+
+		public Person(int age)
+		{
+			_cardInfo = new();
+			_age = age;
+		}
+
+		public virtual int Id
+		{
+			get { return _id; }
+			set { _id = value; }
+		}
+
+		public virtual int Age
+		{
+			get { return _age; }
+			set { _age = value; }
+		}
+
+		public virtual CardInfo CardInfo
+		{
+			get { return _cardInfo; }
+			set { _cardInfo = value; }
+		}
+	}
+}