[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





 Hi,
  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 {

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

    private String name;

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

    @Version
    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) {
        comments.add(comment);
    }
}

@Embeddable
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:
https://hibernate.atlassian.net/browse/HHH-9636

Vlad Mihalcea


    


More information about the hibernate-dev mailing list