Hibernate version:2.1.6 
Mapping documents:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
    <class
        name="com.fabrica.locanet.Product"
        table="product"
        dynamic-update="false"
        dynamic-insert="false"
    >
        <id
            name="id"
            column="id"
            type="long"
        >
            <generator class="increment">
            </generator>
        </id>
        <many-to-one
            name="category"
            class="com.fabrica.locanet.Category"
            cascade="none"
            outer-join="auto"
            update="true"
            insert="true"
            access="property"
            column="categoryId"
            not-null="true"
        />
        <property
            name="name"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="name"
            length="50"
            not-null="true"
        />
        <property
            name="salePrice"
            type="java.math.BigDecimal"
            update="true"
            insert="true"
            access="property"
            column="salePrice"
            length="2"
            not-null="true"
        />
        <property
            name="rentalPrice"
            type="java.math.BigDecimal"
            update="true"
            insert="true"
            access="property"
            column="rentalPrice"
            length="2"
            not-null="true"
        />
        <property
            name="saleAmount"
            type="int"
            update="true"
            insert="true"
            access="property"
            column="saleAmount"
        />
        <property
            name="created"
            type="java.util.Date"
            update="true"
            insert="true"
            access="property"
            column="created"
            not-null="true"
        />
        <property
            name="release"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="release"
            not-null="true"
        />
        <property
            name="description"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
        >
            <column
                name="description" 
                not-null="true"
                sql-type="text"
            />
        </property>
        <set
            name="rentalProducts"
            lazy="true"
            inverse="true"
            cascade="all-delete-orphan"
            sort="unsorted"
            order-by="id asc"
        >
              <key
                  column="productId"
              >
              </key>
              <one-to-many
                  class="com.fabrica.locanet.RentalProduct"
              />
        </set>
        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-Product.xml
            containing the additional properties and place it in your merge dir.
        -->
        <joined-subclass
            name="com.fabrica.locanet.Film"
            dynamic-update="false"
            dynamic-insert="false"
        >
        <key
            column="id"
        />
        <property
            name="title"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="title"
            length="100"
            not-null="true"
        />
        <property
            name="country"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="country"
            length="50"
            not-null="true"
        />
        <property
            name="year"
            type="int"
            update="true"
            insert="true"
            access="property"
            column="year"
            not-null="true"
        />
        <property
            name="runningTime"
            type="int"
            update="true"
            insert="true"
            access="property"
            column="runningTime"
        />
        <set
            name="directors"
            table="FILM_DIRECTOR"
            lazy="true"
            inverse="false"
            cascade="save-update"
            sort="unsorted"
        >
              <key
                  column="FILM_ID"
              >
              </key>
              <many-to-many
                  class="com.fabrica.locanet.Artist"
                  column="DIRECTOR_ID"
                  outer-join="auto"
               />
        </set>
        <set
            name="actors"
            table="FILM_ACTOR"
            lazy="true"
            inverse="false"
            cascade="save-update"
            sort="unsorted"
        >
              <key
                  column="FILM_ID"
              >
              </key>
              <many-to-many
                  class="com.fabrica.locanet.Artist"
                  column="ACTOR_ID"
                  outer-join="auto"
               />
        </set>
        </joined-subclass>
    </class>
</hibernate-mapping>
Name and version of the database you are using:postgresql 7.2
Hi,
In my application I lock (using session.refresh() or session.load()) an object, update it and commit the transaction. When running multiple threads I started to read out-of-date data from the object.
Here's my thread's run code:
Code:
public void run(){
   ... //obtain session
   session.beginTransaction();
   session.refresh(product,LockMode.UPGRADE);
   if(product.getAmount()>0){
      product.decreaseAmount();
      session.update(product);
      System.out.println("product updated");
   }
   else{
      System.out.println("product out of stock");
   }
   session.commit();
   session.close();
}
After running this code I noticed I was getting more "product updated" messages than there should be. I tryied to replace 
session.refresh(..) to 
session.load(..) but the problem happened again. When I looked at the Hibernate SQL output I found out that hibernate first loads my object data and only after that it locks the object. Please take a look at the SQL code and see what I mean:
Code:
Hibernate: select product0_.id as id1_, case when product0__1_.id is not null then 1 when product0_.id is not null then 0 end as clazz_1_, product0_.categoryId as categoryId1_1_, product0_.name as name1_1_, product0_.salePrice as salePrice1_1_, product0_.rentalPrice as rentalPr5_1_1_, product0_.saleAmount as saleAmount1_1_, product0_.created as created1_1_, product0_.release as release1_1_, product0_.description as descript9_1_1_, product0__1_.title as title2_1_, product0__1_.country as country2_1_, product0__1_.year as year2_1_, product0__1_.runningTime as runningT5_2_1_, category1_.id as id0_, category1_.name as name0_, category1_.parentId as parentId0_ from product product0_ left outer join Film product0__1_ on product0_.id=product0__1_.id left outer join category category1_ on product0_.categoryId=category1_.id where product0_.id=?
Hibernate: select children0_.parentId as parentId__, children0_.id as id__, children0_.id as id0_, children0_.name as name0_, children0_.parentId as parentId0_ from category children0_ where children0_.parentId=? order by children0_.name asc
Hibernate: select id from product where id =? for update
I think that the order of the SQL statements is causing the problem. I think hibernate should lock the object before loading its data.
I solved this issue by locking the object before refreshing it:
Code:
public void run(){
   ... //obtain session
   session.beginTransaction();
   session.lock(product,LockMode.UPGRADE);
   session.refresh(product);
   if(product.getAmount()>0){
      product.decreaseAmount();
      session.update(product);
      System.out.println("product updated");
   }
   else{
      System.out.println("product out of stock");
   }
   session.commit();
   session.close();
}
My question: is this the correct behavior of session.refresh() and session.load()? Is there another way to solve my problem?
My Product class is a generic class so that other classes can inherit from it. For example, I have a Film object that extends Product. Please, take a look at the Product mapping file for more information about this. Do you think inheritance is causing this problem?
Thanks,
Jair Jr