-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: setReadOnly() -> "natural identifier was altered&quo
PostPosted: Mon Feb 04, 2008 6:28 am 
Newbie

Joined: Wed Jan 09, 2008 7:16 am
Posts: 7
A have a trouble with Hibernate.

In a nutshell: I fetch an instance of class with natural-id from database. I do session.setReadOnly(thatInstance, true). After that I fetch something else from DB, which results in org.hibernate.HibernateException: immutable natural identifier of an instance of <ThatClass> was altered. If I remove setReadOnly() it works just fine.

I have a class with natural identifier mapped as:

Code:
<class name="Attribute" discriminator-value="0">
  <id name="id" type="integer">
   <generator class="seqhilo">
    <param name="sequence">ATTRIBUTE_SEQ</param>
    <param name="max_lo">10</param>
   </generator>
  </id>
 
  <discriminator type="integer" column="TYPE_ID" />
 
  <natural-id>
   <many-to-one name="section"
        not-null="true"
        class="GoodsSection"
        column="SECTION_ID"
        insert="false" update="false" />
   <property name="outerId" not-null="true" />
  </natural-id>
 
  <subclass name="ru.sbtc.shop.value_object.attribute.IntAttribute" discriminator-value="1" />
...
  <subclass name="ru.sbtc.shop.value_object.attribute.URLAttribute" discriminator-value="11" />

</class>


I do
Code:
  Attribute attr = Attribute.findBySectionAndOuterId(GoodsSection.root(), "image", false);
  session.setReadOnly(attr, true);
 
  AttributeType.getAll();


And I get an exception:
Code:
org.hibernate.HibernateException: immutable natural identifier of an instance
of ru.sbtc.shop.value_object.attribute.ImageFileAttribute was altered
        at org.hibernate.event.def.DefaultFlushEntityEventListener.checkNaturalId(DefaultFlushEntityEventListener.java:94)
        at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:169)
        at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:120)
        at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:196)
        at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76)
        at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:35)
        at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:969)
        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1114)
        at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
        at ru.sbtc.shop.value_object.AttributeType.getAll(AttributeType.java:95)


AttributeType is a rather boring class which have no direct references on Attribute and vice versa.

I do not want this exception to happen since I don't modify that Attribute.
And I don't understand why hibernate checks that if I've declated that instance as read-only - isn't it supposted to NOT ditry-check and NOT try to persist it?

P.S. Maybe I'm doing the wrong thing.
What I need is preview mode: I.e. I make some changes to object, getAsXML() it to build preview changes page, but surely don't want to persist it because that's a preview only. I haven't found the right way to do that how would you do that?

P.P.S. I've found this:
[url=http://lists.jboss.org/pipermail/hibernate-issues/2006-November.txt.gz]> i just upgraded from 3.0.5 to 3.1.2, and i started seeing this problem. i'm not exactly sure where the bug is here, but this is what i'm seeing:
> i have a class, Subscription, which has a natural-id of class Subscriber and Edition (excerpts of relevant mapping files below).
> when Subscription is unloaded, if i make a change, then commit the session, i see this exception:
> HibernateException: immutable natural identifier of an instance of Subscription was altered
> this gets thrown from DefaultFlushEntityEventListener.checkNaturalId() line 80.
> i traced through that method, this is what happens:
> 1. in checkNaturalId, loaded == null , so getNaturalIdSnapshot() is called
> 2. this ends up generating some sql that selects the SubscriptionId and EditionId from the Subscription row.
> 3. the sql is generated in AbstractEntityPersister.getNaturalIdentifierSnapshot(), which calls hydrate for each returned column of the natural-id,
> 4. but hydrate only returns the id, instead of the actual entity
> 5. so this array of ids (instead of entities) ends up back in DefaultFlushEntityEventListener.checkNaturalId() as 'loaded', which gets compared to 'current'
> the trouble is that 'current' contains the entities, but 'loaded' only contains the ids of those entites, so the natural-id check fails, and i get the exception.
> this only happens when 'loaded' is null in checkNaturalId().
> the javadocs for hydrate say you have to call "resolve" afterwards... this isn't being done, so maybe thats the fix. if the natural-id is not just simple properties, then resolve should also be called.[/url]
Did I stumble on that bug? Are there any fixes? I use Hibernate 3.2.5 ga.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 04, 2008 5:15 pm 
Newbie

Joined: Wed Jan 09, 2008 7:16 am
Posts: 7
Looks like this forum isn't suited for questions harder than "my hello world doesn't work" or "please do my homework"...


Top
 Profile  
 
 Post subject: "Come again?"
PostPosted: Wed Feb 06, 2008 11:01 am 
Newbie

Joined: Wed Jan 09, 2008 7:16 am
Posts: 7
Also, that fails:

Code:
Attribute attr = Attribute.findBySectionAndOuterId(GoodsSection.root(), "image", false);
ActionHelper.getSessionFactory().getCurrentSession().evict(attr);
attr.save();


with

Code:
org.hibernate.HibernateException: immutable natural identifier of an instance of ru.sbtc.shop.value_object.attribute.ImageFileAttribute was altered
    at org.hibernate.event.def.DefaultFlushEntityEventListener.checkNaturalId(DefaultFlushEntityEventListener.java:94)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:169)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:120)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:196)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)


Is there something about objects with natural-id which prevents their successfull reattachment after detach/evict()/setReadOnly()?

Why doesn't then doc state "Do not use natural-id if you don't want hole in your feet"?

Or maybe I still do something wrong?


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

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.