[hibernate-dev] JPA PessimisticLockScope.EXTENDED specs are not properly implemented

Mihalcea Vlad mih_vlad at yahoo.com
Fri Feb 27 18:07:12 EST 2015

  According to JPA specification, when using PessimisticLockScope.EXTENDED:
In addition to the behavior for PessimisticLockScope.NORMAL, element collections and relationships owned by the entity that are contained in join tables will be locked if the javax.persistence.lock.scope property is specified with a value of PessimisticLockScope.EXTENDED. The state of entities referenced by such relationships will not be locked (unless those entities are explicitly locked). Locking such a relationship or element collection generally locks only the rows in the join table or collection table for that relationship or collection. This means that phantoms will be possible.
So if I define the following Parent/Child associations:@Entity
public class Post {

    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;

    private String name;

    @JoinTable(name = "post_comments", joinColumns = @JoinColumn(name = "post_id"))
    @OrderColumn(name = "comment_index")
    private List<Comment> comments = new ArrayList<Comment>();

    private int version;

    public Long getId() {
        return id;

    public void setId(Long id) {
        this.id = id;

    public String getName() {
        return name;

    public void setName(String name) {
        this.name = name;

    public List<Comment> getComments() {
        return comments;

    public final int getVersion() {
        return version;

    public void addComment(Comment comment) {

public class Comment {

    private String review;

    public String getReview() {
        return review;

    public void setReview(String review) {
        this.review = review;
Because a Post has a collection of Comment components, an EXTENDED lock request should lock the joined table rows as well, without locking the actual Comment row-level locks:Post post = entityManager.find(Post.class, parentId);
entityManager.lock(post, LockModeType.PESSIMISTIC_WRITE, Collections.singletonMap("javax.persistence.lock.scope", (Object) PessimisticLockScope.EXTENDED));
                return null;
But the output SQL looks like this:Unable to find source-code formatter for language: shell. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xmlINFO  [main]: n.t.d.l.CommonsQueryLoggingListener - Name:, Time:0, Num:1, Query:{[select post0_.id as id1_16_0_, post0_.name as name2_16_0_, post0_.version as version3_16_0_ from Post post0_ where post0_.id=?][1]} 
INFO  [main]: n.t.d.l.CommonsQueryLoggingListener - Name:, Time:1, Num:1, Query:{[select id from Post where id =? and version =? for update][1,0]} 
So, only the root Entity was locked, when we should have locked the post_comments associated rows as well.
Code available on GitHub. You have to run the HibernateCascadeLockComponentTest test. 
This issue is also described on JIRA:

Vlad Mihalcea


More information about the hibernate-dev mailing list