-->
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.  [ 7 posts ] 
Author Message
 Post subject: How to handle dirty check without select or cache?
PostPosted: Mon Nov 07, 2005 11:36 am 
Newbie

Joined: Mon Jan 24, 2005 6:05 pm
Posts: 12
I am new to hibernate so i want to discuss with the hibernate community the best way to implement following solution to handle ditry check without select before update or force action to be in the same transaction.


// object which extends by all the pojos

PersistObject
// 0 = new
// 1 = unmodified
// 2 = updated
// 3 = delete
getStatus() : int


User
getAddressSet()
getAddress(addressId)
removeAddress(addressId)
addAddress(address)

// load user object in new session.
USer user = session.load(user.class, new Long(1));

// trying to update in a new session.
// get address object from convinient method.
UserAddress address = user.getAddress(10)
// modified some userAddress attribute, calling this method also trigger status to set to modified.
address.setStreet1("white house");

// remove address does not cause the address to be removed from collection
// instead it only marks object as candidate to be removed when reattaching occurred
user.removeAddress(11)

// add a NEW address, assuming address does not have none-null properties
user.addAddress(new address())

// call to persist
session.saveOrUpdate(user);


Here is what should happen when hibernate trying to persist the user instant.

1) checks the status of user object. It's unmodified. No update.
2) now iterate over the addressSet collection, assuming that there is 3 items in the collection.
a) check the status of first UserAddress. It's unmodified. No update.
b) check the status of second UserAddress. It's modified. Issue an update.
c) check the status of third UserAddress. It's marked deleted. Issue an delete.
d) check the status of forth UserAddress. It's marked as new. Issue an insert.

Is there a way to persist object as what i described by extending hibernate? Please give me some lead. I think it's possible to avoid select before update or force action to be in same session with extra information and code that I am willing to sacrisfy.


Thanks in advance.


Top
 Profile  
 
 Post subject: another question
PostPosted: Mon Nov 07, 2005 12:03 pm 
Newbie

Joined: Mon Jan 24, 2005 6:05 pm
Posts: 12
how can i set unsaved-value to be less than 0? thanks


Top
 Profile  
 
 Post subject: please help
PostPosted: Mon Nov 07, 2005 2:53 pm 
Newbie

Joined: Mon Jan 24, 2005 6:05 pm
Posts: 12
I will blow a credit if someone can point me at the right direction. Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 9:34 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Hibernate already does what your original question asks. You don't even need the saveOrUpdate, because you have loaded the User object and you haven't discarded the Session. You can just flush the user from the session and it will work as you want it to (asuming that you have the appropriate cascade options).

If you particularly want a removeAddress method to leave the address accessible to getAddress() but remove it from the DB when you next flush/save, then I recommend implementing a save method for user objects, which removes marked objects from the persistent collection before calling saveOrUpdate or flush. It's not a good idea to do it this way, at least not in application code. Maybe you should implement a factory for saving this object? Or even better, use hibernate's Interceptor functionality and remove marked items in the preFlush method for the User class.

I don't think I understand your unsaved-value question. Does
Code:
  <id name="id" column="id" type="integer" unsaved-value="-1">
    <generator .../>
  </id>

not do what you want it to?


Top
 Profile  
 
 Post subject: Thank you so much but....
PostPosted: Mon Nov 07, 2005 10:08 pm 
Newbie

Joined: Mon Jan 24, 2005 6:05 pm
Posts: 12
tenwit wrote:
Hibernate already does what your original question asks. You don't even need the saveOrUpdate, because you have loaded the User object and you haven't discarded the Session. You can just flush the user from the session and it will work as you want it to (asuming that you have the appropriate cascade options). [/qoute]

Maybe I didn't specify my question clear enough. I meant how to implement similar solution without force action to be in the same transaction.

Here is the senari, RMI send the object to the client side, and UI make some change to one of the userAddress in the set and send back the whole object. Then reattach happen in a new session. I want to only deal with user object without the side effect. In other word, update dirty object without redundant update and select. I read a little more on the extending hibernate, maybe pre-insert-and-pre-update would be good place to filter out unneccessary update. But the whole event listener thing is still under progress. I tried release candiate 2 but rollback to 3.05.


tenwit wrote:
If you particularly want a removeAddress method to leave the address accessible to getAddress() but remove it from the DB when you next flush/save, then I recommend implementing a save method for user objects, which removes marked objects from the persistent collection before calling saveOrUpdate or flush. It's not a good idea to do it this way, at least not in application code. Maybe you should implement a factory for saving this object? Or even better, use hibernate's Interceptor functionality and remove marked items in the preFlush method for the User class.


I will look into interceptor, any helpful documentation will great appricated.

[qoute="tenwit"]
I don't think I understand your unsaved-value question. Does
Code:
  <id name="id" column="id" type="integer" unsaved-value="-1">
    <generator .../>
  </id>

not do what you want it to?

I want to know if there is a way to specify all number less than 0 consider to be new object. If I can tailor this bahavior, then i can attach multiple new object by manually assigned unique ids (negative) to a collection without worry about equals and hashcode not working correctly.

Code:
  public boolean equals(Object rhs) {
    if (rhs == null)
      return false;
    if (! (rhs instanceof Person))
      return false;
    Person that = (Person) rhs;
    if (this.getId() == null || that.getId() == null)
      return false;
    return (this.getId().equals(that.getId()));
  }

  public int hashCode() {
    if (this.hashValue == 0) {
      int result = 17;
      int idValue = this.getId() == null ? 0 : this.getId().hashCode();
      result = result * 37 + idValue;
      this.hashValue = result;
    }
    return this.hashValue;
  }


lastly, thank you for replay my post.


Top
 Profile  
 
 Post subject: Thank you so much but....
PostPosted: Mon Nov 07, 2005 10:12 pm 
Newbie

Joined: Mon Jan 24, 2005 6:05 pm
Posts: 12
tenwit wrote:
Hibernate already does what your original question asks. You don't even need the saveOrUpdate, because you have loaded the User object and you haven't discarded the Session. You can just flush the user from the session and it will work as you want it to (asuming that you have the appropriate cascade options).


Maybe I didn't specify my question clear enough. I meant how to implement similar solution without force action to be in the same transaction.

Here is the senari, RMI send the object to the client side, and UI make some change to one of the userAddress in the set and send back the whole object. Then reattach happen in a new session. I want to only deal with user object without the side effect. In other word, update dirty object without redundant update and select. I read a little more on the extending hibernate, maybe pre-insert-and-pre-update would be good place to filter out unneccessary update. But the whole event listener thing is still under progress. I tried release candiate 2 but rollback to 3.05.


tenwit wrote:
If you particularly want a removeAddress method to leave the address accessible to getAddress() but remove it from the DB when you next flush/save, then I recommend implementing a save method for user objects, which removes marked objects from the persistent collection before calling saveOrUpdate or flush. It's not a good idea to do it this way, at least not in application code. Maybe you should implement a factory for saving this object? Or even better, use hibernate's Interceptor functionality and remove marked items in the preFlush method for the User class.


I will look into interceptor, any helpful documentation will great appricated.

[qoute="tenwit"]
I don't think I understand your unsaved-value question. Does
Code:
  <id name="id" column="id" type="integer" unsaved-value="-1">
    <generator .../>
  </id>

not do what you want it to?[/quote]
I want to know if there is a way to specify all number less than 0 consider to be new object. If I can tailor this bahavior, then i can attach multiple new object by manually assigned unique ids (negative) to a collection without worry about equals and hashcode not working correctly.

Code:
  public boolean equals(Object rhs) {
    if (rhs == null)
      return false;
    if (! (rhs instanceof Person))
      return false;
    Person that = (Person) rhs;
    if (this.getId() == null || that.getId() == null)
      return false;
    return (this.getId().equals(that.getId()));
  }

  public int hashCode() {
    if (this.hashValue == 0) {
      int result = 17;
      int idValue = this.getId() == null ? 0 : this.getId().hashCode();
      result = result * 37 + idValue;
      this.hashValue = result;
    }
    return this.hashValue;
  }


lastly, thank you for replay my post.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 10:27 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Maybe I didn't specify my question clear enough. I meant how to implement similar solution without force action to be in the same transaction.

I came across someone else proposing a solution to this problem on this site, earlier today. Can't remember if it was here on the forums, or on the wiki. I'm afraid I'm too dehydrated and tired to search for it right now, but to sum up: it's dificult and complex. In the interest of getting you app working first, just always save everything. Perfect it later.

I want to know if there is a way to specify all number less than 0 consider to be new object. If I can tailor this bahavior, then i can attach multiple new object by manually assigned unique ids (negative) to a collection without worry about equals and hashcode not working correctly.

I think that you're doing this the wrong way around. Set your id as null, keep unsaved-value="null", and write a custom generator to come up with your id at save time. Hibernate will call your generate method at the right time. Don't generate your id in business logic.

equals and hashCode

These are perfect examples of the absolute worst possible kinds of equals() and hashCode(). Sorry to be cruel, I'm doing it to be kind. It's not specifically a hibernate thing: even if you were using plain old JDBC, this would be wrong. Before you save your object, your id would have one value (null, your proposed negative value, whatever). You put it in a hashmap. You save it (not from the hashmap, from some other reference). Your hashmap is now wrong: the same object now has a different hashcode. If you clone the object (b = a.clone()) you would expect a.equals(b) to return true: if you save a, suddently a.equals(b) will return false, because the id has changed. Don't do this.

Read the hashCode/equals javadocs, or this article: http://www.hibernate.org/109.html


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.