Hibernate Books

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Excessive update in presence of composite-element
PostPosted: Fri Dec 09, 2011 12:08 pm 
Newbie

Joined: Wed Jul 27, 2011 11:38 am
Posts: 1
Hello,

I have a Person class that has (via composition) a set of Addresses. I'm surprised by the SQL generated by the following scenario: create and persist one Person, load all Persons, create and persist another Person. It seems that saving the second Person triggers an update on the first Person.

My version of NHibernate is 3.1.0.4000.

The mapping:

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="NHib"
                   namespace="NHib"
                   >
  <class name="Person">
    <id name="Id">
      <generator class="guid" />
    </id>
    <version name="Version" column="version" />
    <property name="Name" />
    <set name="Address" lazy ="true">
      <key column="id" />
      <composite-element class="Address">
        <property name="Number" />
        <property name="Street" />
      </composite-element>
    </set>
  </class>
</hibernate-mapping>


...and the code:

Code:
  class Address
  {
    public int Number { get; set; }
    public string Street { get; set; }
  }

  class Person
  {
    public virtual Guid Id { get; set; }
    public virtual int Version { get; set; }
    public virtual string Name { get; set; }
    public virtual ICollection<Address> Address { get; set; }
  }

  class Program
  {
    static void Main(string[] args)
    {
      System.Console.SetOut(new DebugTextWriter());

      var cfg = new Configuration();
      cfg.Configure();
      cfg.AddAssembly(typeof(Person).Assembly);

      var sessionFactory = cfg.BuildSessionFactory();

      using (var session = sessionFactory.OpenSession())
      {
        new SchemaExport(cfg).Execute(false, true, false, session.Connection, Console.Out);

        var god = new Person()
                    {
                      Name = "God",
                      Address = new List<Address>()
                                  {
                                    new Address() { Number = 1, Street = "Heavens"},
                                  }
                    };

        using (var transaction = session.BeginTransaction())
        {
          session.Save(god);
          transaction.Commit(); // 1
        }

        var persons = session.CreateCriteria<Person>().List(); // 2

        var devil = new Person()
        {
          Name = "Devil",
          Address = new List<Address>()
                                  {
                                    new Address() { Number = 1, Street = "Hell"},
                                  }
        };

        using (var transaction = session.BeginTransaction())
        {
          session.Save(devil);
          transaction.Commit(); // 3
        }
      }
    }
  }


In the first commit (marked //1) the generated SQL is:

Code:
NHibernate: INSERT INTO Person (version, Name, Id) VALUES (@p0, @p1, @p2);@p0 = 1 [Type: Int32 (0)], @p1 = 'God' [Type: String (0)], @p2 = 30c30ca0-6637-490a-a1fd-32f8044bafb4 [Type: Guid (0)]
NHibernate: UPDATE Person SET version = @p0, Name = @p1 WHERE Id = @p2 AND version = @p3;@p0 = 2 [Type: Int32 (0)], @p1 = 'God' [Type: String (0)], @p2 = 30c30ca0-6637-490a-a1fd-32f8044bafb4 [Type: Guid (0)], @p3 = 1 [Type: Int32 (0)]
NHibernate: INSERT INTO Address (id, Number, Street) VALUES (@p0, @p1, @p2);@p0 = 30c30ca0-6637-490a-a1fd-32f8044bafb4 [Type: Guid (0)], @p1 = 1 [Type: Int32 (0)], @p2 = 'Heavens' [Type: String (0)]
NHibernate: SELECT this_.Id as Id0_0_, this_.version as version0_0_, this_.Name as Name0_0_ FROM Person this_


I pretty much agree with it, although it looks like the UPDATE could be spared.

Same when loading all the Persons (//2):

Code:
NHibernate: SELECT this_.Id as Id0_0_, this_.version as version0_0_, this_.Name as Name0_0_ FROM Person this_


However, on the second commit (//3) I see:

Code:
NHibernate: INSERT INTO Person (version, Name, Id) VALUES (@p0, @p1, @p2);@p0 = 1 [Type: Int32 (0)], @p1 = 'Devil' [Type: String (0)], @p2 = d1834ca4-fa13-441d-b68c-1d832ffc0694 [Type: Guid (0)]
NHibernate: UPDATE Person SET version = @p0, Name = @p1 WHERE Id = @p2 AND version = @p3;@p0 = 3 [Type: Int32 (0)], @p1 = 'God' [Type: String (0)], @p2 = 66e155c1-7131-4fbb-88de-644dbdc2530c [Type: Guid (0)], @p3 = 2 [Type: Int32 (0)]
NHibernate: UPDATE Person SET version = @p0, Name = @p1 WHERE Id = @p2 AND version = @p3;@p0 = 2 [Type: Int32 (0)], @p1 = 'Devil' [Type: String (0)], @p2 = d1834ca4-fa13-441d-b68c-1d832ffc0694 [Type: Guid (0)], @p3 = 1 [Type: Int32 (0)]
NHibernate: DELETE FROM Address WHERE id = @p0 AND Number = @p1 AND Street = @p2;@p0 = 66e155c1-7131-4fbb-88de-644dbdc2530c [Type: Guid (0)], @p1 = 1 [Type: Int32 (0)], @p2 = 'Heavens' [Type: String (0)]
NHibernate: INSERT INTO Address (id, Number, Street) VALUES (@p0, @p1, @p2);@p0 = 66e155c1-7131-4fbb-88de-644dbdc2530c [Type: Guid (0)], @p1 = 1 [Type: Int32 (0)], @p2 = 'Heavens' [Type: String (0)]
NHibernate: INSERT INTO Address (id, Number, Street) VALUES (@p0, @p1, @p2);@p0 = d1834ca4-fa13-441d-b68c-1d832ffc0694 [Type: Guid (0)], @p1 = 1 [Type: Int32 (0)], @p2 = 'Hell' [Type: String (0)]


What's the reason for this messing with the first Person ? Can it be avoided ?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.