-->
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.  [ 6 posts ] 
Author Message
 Post subject: Hibernate change/reset data during a read
PostPosted: Wed Jul 12, 2006 9:22 pm 
Beginner
Beginner

Joined: Fri Mar 12, 2004 1:02 pm
Posts: 23
Hi,

I'm encountering an issue where hibernate changes data on a read. In my application, I have hibernate save my data into a database. And then on a subsequent read, it seems to retrieve the data but resets the value columns before doing a read. For example, I have the following record saved to my CONTAINER table:

Code:
CONTAINER_ID | ITEM_ID | VALUE
1            | 1       | 100.0


When I do the subsequent read, the table looks like this:

Code:
CONTAINER_ID | ITEM_ID | VALUE
1            | 1       | 0.0


Any ideas why hibernate would change the values during a read? I'm totally perplexed right now. Thanks in advance!

-los


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 12, 2006 9:45 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
It wouldn't. Something else is going on. First check for triggers on the table; if that's not it, you'll have to examine your mappings and data access code to see what would cause that.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 13, 2006 12:35 pm 
Beginner
Beginner

Joined: Fri Mar 12, 2004 1:02 pm
Posts: 23
Thanks for the reply,

You're right. I realized that my setValue() method has a condition... it checks to see if the item is in stock. The issue now is, can I tell hibernate which order to populate the fields when doing a read? Here is my Item code:

Code:
public abstract class Item {
   private boolean inStock;
   private BigDecimal value;

   public void setInStock(boolean inStock) {
     this.inStock = inStock;
  }

   public void setValue(BigDecimal value) {
    if (inStock) {
     this.value = value;
   }

   else {
     this.value = BigDecimal.ZERO;
   }
}


Below is my Item table (w/inStock field):

Code:
CONTAINER_ID | ITEM_ID | VALUE | IN_STOCK
1            | 1       | 100.0  | 1


When debugging the code, the inStock variable is false during the setValue call--telling me that the field did not get set before the call to setValue(). So I would like Hibernate to call setInStock before setValue when it reads from the DB. Is this possible? Thanks in advance!

-los


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 13, 2006 7:02 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
To do this, have a property (InternalValue) that you map in the normal way, with methods setInternalValue and getInternalValue. These are only in your impl class, not your interfance. In your impl and interface, have getValue() and setValue() methods that are not in your mapping file. Put the logic in setValue, and have setInternalValue do the raw, basic assignment.

This way, when hibernate calls setInternalValue(valueFromDB), there's no special code being called, and that's the correct way to do it: if it's in the DB, then it has already passed your special code in setValue(valueFromUser).

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 14, 2006 11:28 am 
Beginner
Beginner

Joined: Fri Mar 12, 2004 1:02 pm
Posts: 23
Never thought of this.

However, how would I go about doing this if the setValue method is actually an overriden one. For example, say my concrete class's setValue() has the logic built in, but the base class's setValue() is simple:

Code:
public abstract class BaseItem {
  private boolean inStock = false;
  private BigDecimal value;

  public void setInStock(boolean inStock) {
    this.inStock = inStock;
  }

  public void setValue(BigDecimal value) {
    this.value = value;
}
}


public class StockItem extends BaseItem {
  public void setValue(BigDecimal value) {
    if (inStock) {
       this.value = value;
    }

   else {
      this.value = BigDecimal.ZERO;
   }
}

public class CustomizedItem extends BaseItem {
  // keeps base class setValue()
}


Know if I use hibernate's table per class hierarchy mixed with table per subclass for these three classes above with your suggestion, it would create duplicate columns-- one for BASE_ITEM table and the other for STOCK_ITEM table... I'm thinking of a hibernate mapping like this:

Code:
<class name="BaseItem" table="BASE_ITEM">
    <id name="id" type="long" column="BASE_ITEM_ID">
        <generator class="native"/>
    </id>
    <discriminator column="ITEM_TYPE" type="string"/>
    <property name="inStock" column="IN_STOCK"/>
    <property name="value" column="VALUE"/>
    ...
    <subclass name="StockItem" discriminator-value="StockItem">
        <join table="STOCK_ITEM">
             <property name="fakeValue" column="FAKE_VALUE"/>
        </join>
    </subclass>
    <subclass name="CustomizedItem" discriminator-value="CustomizedItem">
        ...
    </subclass>
</class>


Hence the tables are not normalized since there will value and fake value, two columns to represent the same thing...


-los


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 16, 2006 5:57 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Assuming that you are using the default access="property", the code you supplied is buggy. You must not refer to member values outside of the getter and setter methods.

Here's the rewritten code:
Code:
public class StockItem extends BaseItem {
  public void setValue(BigDecimal value) {
    if (inStock) {
       super.setValue(value);
    }

   else {
      super.setValue(BigDecimal.ZERO);
   }
}
As you can see, this requires no further correction: super.setValue() is the correct method to call, as it calls super.setIntervalValue(), which CGLib will have enhanced (if necessary). And the only thing you have to remember is that you must use the potentially-enhanced method to do the setting of any property; you must not skip the method call and set the member variable directly.

_________________
Code tags are your friend. Know them and use them.


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