[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