Search code examples
hibernatelockingpessimistic-locking

Hibernate pessimistic locking do not work with polymorphic query


I have a following class hierarchy:

@Entity
@Table(name = "BaseThing")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class BaseThing implements Serializable {

    @Id
    @Column(name = "id", nullable = false)
    private Long id;

    @Basic(optional = false)
    @Column(name = "name", nullable = false, length = 48)
    private String name;
    ...
}

@Entity
@Table(name = "ConcreteThing")
public class ConcreteThing extends BaseThing {

    @Column(name = "aprop", nullable = false, length = 12)
    private String aProp;

    ...
}

@Entity
@Table(name = "AnotherConcreteThing")
public class AnotherConcreteThing extends BaseThing {

    @Column(name = "anotherprop", nullable = false, length = 12)
    private String anotherProp;

    ...
}

I'm trying to read and lock a ConcreteThing instance so no other transaction could read it, using hibernate LockOptions.UPGRADE.

Now the function:

BaseThing thing = (BaseThing) session.get(BaseThing.class, id, LockOptions.UPGRADE);

is not working - a "select for update" syntax is not generated by hibernate so there is no pessimistic locking on that object

while:

BaseThing entity = (BaseThing) session.get(BaseThing.class, id);
session.refresh(entity, LockOptions.UPGRADE));

is working - a "select for update" syntax is generated for the refresh operation.

The diffrence between refresh() and get() functions, is that the get() function uses an outer left join to select the concrete object, and refresh() uses an inner join to select the concrete object.

is there a difference between those joins in the context of pessimistic locking?

Thanks!


Solution

  • Some databases do not support select for update with outer join.

    in my case im using DB2 version 10.5, that supports. so the problem remains.

    After digging in hibernate code, i found out that DB2Dialect have a function supportsOuterJoinForUpdate() that return false, while suppose to return true because BD2 supports this kind of select. this is an hibernate bug. extending DB2Dialect and returning true for that function, fixed the problem for me.