滕州 网站 建设,画家网站建设,wordpress数字中文主题,保定住房和城乡建设局网站介绍 Hibernate提供了一种乐观的锁定机制 #xff0c;即使长时间通话也可以防止丢失更新 。 结合实体存储#xff0c;跨越多个用户请求#xff08;扩展的持久性上下文或分离的实体#xff09;#xff0c;Hibernate可以保证应用程序级的可重复读取 。 脏检查机制检测实体状… 介绍 Hibernate提供了一种乐观的锁定机制 即使长时间通话也可以防止丢失更新 。 结合实体存储跨越多个用户请求扩展的持久性上下文或分离的实体Hibernate可以保证应用程序级的可重复读取 。 脏检查机制检测实体状态更改并增加实体版本。 尽管始终会考虑基本属性更改但是Hibernate集合在这方面更加微妙。 拥有与反向收藏 在关系数据库中两个记录通过外键引用关联。 在这种关系中引用记录是父记录而引用行外键侧是子记录。 非空外键只能引用现有的父记录。 在面向对象的空间中可以在两个方向上表示这种关联。 我们可以从孩子到父母有一对多的引用而父母也可以有一对多的孩子集合。 因为双方都有可能控制数据库外键状态所以我们必须确保只有一方是此关联的所有者。 仅拥有方状态更改会传播到数据库。 非持有端历来称为逆侧。 接下来我将描述对该关联进行建模的最常用方法。 单向父项拥有子项关联映射 只有父方具有OneToMany非逆子级集合。 子实体完全不引用父实体。 Entity(name post)
public class Post {...OneToMany(cascade CascadeType.ALL, orphanRemoval true)private ListComment comments new ArrayListComment();...
}单向父-子-子-子组件关联映射映射 子端不一定总是必须是实体我们可以将其建模为组件类型 。 一个Embeddable对象组件类型可以同时包含基本类型和关联映射但是它永远不能包含Id。 可嵌入对象及其拥有的实体将被持久保存/删除。 父级具有ElementCollection子级关联。 子实体只能通过不可查询的特定于 Hibernate的Parent注释引用父实体。 Entity(name post)
public class Post {...ElementCollectionJoinTable(name post_comments, joinColumns JoinColumn(name post_id))OrderColumn(name comment_index)private ListComment comments new ArrayListComment();...public void addComment(Comment comment) {comment.setPost(this);comments.add(comment);}
} Embeddable
public class Comment {...Parentprivate Post post;...
}双向父子侧子关联映射 父级是拥有方因此它有一个OneToMany非逆没有mappedBy指令子级集合。 子实体通过ManyToOne关联引用父实体该关联既不可插入也不可更新 Entity(name post)
public class Post {...OneToMany(cascade CascadeType.ALL, orphanRemoval true)private ListComment comments new ArrayListComment();...public void addComment(Comment comment) {comment.setPost(this);comments.add(comment);}
} Entity(name comment)
public class Comment {...ManyToOneJoinColumn(name post_id, insertable false, updatable false)private Post post;...
}双向儿童拥有侧-父母关联映射 子实体通过引用父实体ManyToOne协会和家长有一个的mappedBy OneToMany孩子集合。 父侧是反侧因此仅ManyToOne状态更改会传播到数据库。 即使只有一个拥有的一方通过使用add / removeChild方法使双方保持同步始终是一个好习惯。 Entity(name post)
public class Post {...OneToMany(cascade CascadeType.ALL, orphanRemoval true, mappedBy post)private ListComment comments new ArrayListComment();...public void addComment(Comment comment) {comment.setPost(this);comments.add(comment);}
} Entity(name comment)
public class Comment {...ManyToOneprivate Post post; ...
}单向儿童拥有侧父母关系映射 子实体通过ManyToOne关联引用父代。 父级没有OneToMany子级集合因此子级实体成为拥有方。 此关联映射类似于关系数据外键链接。 Entity(name comment)
public class Comment {...ManyToOneprivate Post post; ...
}集合版本控制 JPA 2.1规范的3.4.2部分将乐观锁定定义为 将对象写入数据库时持久性提供程序运行时会更新version属性。 所有非关系字段和适当的关系以及实体所拥有的所有关系都包含在版本检查中[35]。 [35]这包括在联接表中维护的拥有的关系 注意只有所有者方的子级集合可以更新父版本。 测试时间 让我们测试一下父子关联类型如何影响父版本。 由于我们对子级集合的脏检查感兴趣因此将跳过单向的子级拥有方-父级关联因为在这种情况下父级不包含子级集合。 测试用例 以下测试用例将用于所有集合类型用例 protected void simulateConcurrentTransactions(final boolean shouldIncrementParentVersion) {final ExecutorService executorService Executors.newSingleThreadExecutor();doInTransaction(new TransactionCallableVoid() {Overridepublic Void execute(Session session) {try {P post postClass.newInstance();post.setId(1L);post.setName(Hibernate training);session.persist(post);return null;} catch (Exception e) {throw new IllegalArgumentException(e);}}});doInTransaction(new TransactionCallableVoid() {Overridepublic Void execute(final Session session) {final P post (P) session.get(postClass, 1L);try {executorService.submit(new CallableVoid() {Overridepublic Void call() throws Exception {return doInTransaction(new TransactionCallableVoid() {Overridepublic Void execute(Session _session) {try {P otherThreadPost (P) _session.get(postClass, 1L);int loadTimeVersion otherThreadPost.getVersion();assertNotSame(post, otherThreadPost);assertEquals(0L, otherThreadPost.getVersion());C comment commentClass.newInstance();comment.setReview(Good post!);otherThreadPost.addComment(comment);_session.flush();if (shouldIncrementParentVersion) {assertEquals(otherThreadPost.getVersion(), loadTimeVersion 1);} else {assertEquals(otherThreadPost.getVersion(), loadTimeVersion);}return null;} catch (Exception e) {throw new IllegalArgumentException(e);}}});}}).get();} catch (Exception e) {throw new IllegalArgumentException(e);}post.setName(Hibernate Master Class);session.flush();return null;}});
}单向父母所有子女的关联测试 #create tables
Query:{[create table comment (id bigint generated by default as identity (start with 1), review varchar(255), primary key (id))][]}
Query:{[create table post (id bigint not null, name varchar(255), version integer not null, primary key (id))][]}
Query:{[create table post_comment (post_id bigint not null, comments_id bigint not null, comment_index integer not null, primary key (post_id, comment_index))][]}
Query:{[alter table post_comment add constraint UK_se9l149iyyao6va95afioxsrl unique (comments_id)][]}
Query:{[alter table post_comment add constraint FK_se9l149iyyao6va95afioxsrl foreign key (comments_id) references comment][]}
Query:{[alter table post_comment add constraint FK_6o1igdm04v78cwqre59or1yj1 foreign key (post_id) references post][]} #insert post in primary transaction
Query:{[insert into post (name, version, id) values (?, ?, ?)][Hibernate training,0,1]} #select post in secondary transaction
Query:{[select entityopti0_.id as id1_1_0_, entityopti0_.name as name2_1_0_, entityopti0_.version as version3_1_0_ from post entityopti0_ where entityopti0_.id?][1]} #insert comment in secondary transaction
#optimistic locking post version update in secondary transaction
Query:{[insert into comment (id, review) values (default, ?)][Good post!]}
Query:{[update post set name?, version? where id? and version?][Hibernate training,1,1,0]}
Query:{[insert into post_comment (post_id, comment_index, comments_id) values (?, ?, ?)][1,0,1]} #optimistic locking exception in primary transaction
Query:{[update post set name?, version? where id? and version?][Hibernate Master Class,1,1,0]}
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.vladmihalcea.hibernate.masterclass.laboratory.concurrency.EntityOptimisticLockingOnUnidirectionalCollectionTest$Post#1]单向父子侧子组件关联测试 #create tables
Query:{[create table post (id bigint not null, name varchar(255), version integer not null, primary key (id))][]}
Query:{[create table post_comments (post_id bigint not null, review varchar(255), comment_index integer not null, primary key (post_id, comment_index))][]}
Query:{[alter table post_comments add constraint FK_gh9apqeduab8cs0ohcq1dgukp foreign key (post_id) references post][]} #insert post in primary transaction
Query:{[insert into post (name, version, id) values (?, ?, ?)][Hibernate training,0,1]} #select post in secondary transaction
Query:{[select entityopti0_.id as id1_0_0_, entityopti0_.name as name2_0_0_, entityopti0_.version as version3_0_0_ from post entityopti0_ where entityopti0_.id?][1]}
Query:{[select comments0_.post_id as post_id1_0_0_, comments0_.review as review2_1_0_, comments0_.comment_index as comment_3_0_ from post_comments comments0_ where comments0_.post_id?][1]} #insert comment in secondary transaction
#optimistic locking post version update in secondary transaction
Query:{[update post set name?, version? where id? and version?][Hibernate training,1,1,0]}
Query:{[insert into post_comments (post_id, comment_index, review) values (?, ?, ?)][1,0,Good post!]} #optimistic locking exception in primary transaction
Query:{[update post set name?, version? where id? and version?][Hibernate Master Class,1,1,0]}
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.vladmihalcea.hibernate.masterclass.laboratory.concurrency.EntityOptimisticLockingOnComponentCollectionTest$Post#1]双向父母拥有-子-孩子关联测试 #create tables
Query:{[create table comment (id bigint generated by default as identity (start with 1), review varchar(255), post_id bigint, primary key (id))][]}
Query:{[create table post (id bigint not null, name varchar(255), version integer not null, primary key (id))][]}
Query:{[create table post_comment (post_id bigint not null, comments_id bigint not null)][]}
Query:{[alter table post_comment add constraint UK_se9l149iyyao6va95afioxsrl unique (comments_id)][]}
Query:{[alter table comment add constraint FK_f1sl0xkd2lucs7bve3ktt3tu5 foreign key (post_id) references post][]}
Query:{[alter table post_comment add constraint FK_se9l149iyyao6va95afioxsrl foreign key (comments_id) references comment][]}
Query:{[alter table post_comment add constraint FK_6o1igdm04v78cwqre59or1yj1 foreign key (post_id) references post][]} #insert post in primary transaction
Query:{[insert into post (name, version, id) values (?, ?, ?)][Hibernate training,0,1]} #select post in secondary transaction
Query:{[select entityopti0_.id as id1_1_0_, entityopti0_.name as name2_1_0_, entityopti0_.version as version3_1_0_ from post entityopti0_ where entityopti0_.id?][1]}
Query:{[select comments0_.post_id as post_id1_1_0_, comments0_.comments_id as comments2_2_0_, entityopti1_.id as id1_0_1_, entityopti1_.post_id as post_id3_0_1_, entityopti1_.review as review2_0_1_, entityopti2_.id as id1_1_2_, entityopti2_.name as name2_1_2_, entityopti2_.version as version3_1_2_ from post_comment comments0_ inner join comment entityopti1_ on comments0_.comments_identityopti1_.id left outer join post entityopti2_ on entityopti1_.post_identityopti2_.id where comments0_.post_id?][1]} #insert comment in secondary transaction
#optimistic locking post version update in secondary transaction
Query:{[insert into comment (id, review) values (default, ?)][Good post!]}
Query:{[update post set name?, version? where id? and version?][Hibernate training,1,1,0]}
Query:{[insert into post_comment (post_id, comments_id) values (?, ?)][1,1]} #optimistic locking exception in primary transaction
Query:{[update post set name?, version? where id? and version?][Hibernate Master Class,1,1,0]}
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.vladmihalcea.hibernate.masterclass.laboratory.concurrency.EntityOptimisticLockingOnBidirectionalParentOwningCollectionTest$Post#1]双向儿童拥有侧-父母关联测试 #create tables
Query:{[create table comment (id bigint generated by default as identity (start with 1), review varchar(255), post_id bigint, primary key (id))][]}
Query:{[create table post (id bigint not null, name varchar(255), version integer not null, primary key (id))][]}
Query:{[alter table comment add constraint FK_f1sl0xkd2lucs7bve3ktt3tu5 foreign key (post_id) references post][]} #insert post in primary transaction
Query:{[insert into post (name, version, id) values (?, ?, ?)][Hibernate training,0,1]} #select post in secondary transaction
Query:{[select entityopti0_.id as id1_1_0_, entityopti0_.name as name2_1_0_, entityopti0_.version as version3_1_0_ from post entityopti0_ where entityopti0_.id?][1]} #insert comment in secondary transaction
#post version is not incremented in secondary transaction
Query:{[insert into comment (id, post_id, review) values (default, ?, ?)][1,Good post!]}
Query:{[select count(id) from comment where post_id ?][1]} #update works in primary transaction
Query:{[update post set name?, version? where id? and version?][Hibernate Master Class,1,1,0]}否决默认集合版本控制 如果默认的拥有方集合版本控制不适合您的用例则始终可以使用Hibernate OptimisticLock注释来取代它。 让我们废除双向parent-owning-side-child关联的默认父版本更新机制 Entity(name post)
public class Post {...OneToMany(cascade CascadeType.ALL, orphanRemoval true)OptimisticLock(excluded true)private ListComment comments new ArrayListComment();...public void addComment(Comment comment) {comment.setPost(this);comments.add(comment);}
} Entity(name comment)
public class Comment {...ManyToOneJoinColumn(name post_id, insertable false, updatable false)private Post post;...
} 这次子级集合更改不会触发父版本更新 #create tables
Query:{[create table comment (id bigint generated by default as identity (start with 1), review varchar(255), post_id bigint, primary key (id))][]}
Query:{[create table post (id bigint not null, name varchar(255), version integer not null, primary key (id))][]}
Query:{[create table post_comment (post_id bigint not null, comments_id bigint not null)][]}
Query:{[alter table post_comment add constraint UK_se9l149iyyao6va95afioxsrl unique (comments_id)][]}
Query:{[alter table comment add constraint FK_f1sl0xkd2lucs7bve3ktt3tu5 foreign key (post_id) references post][]}
Query:{[alter table post_comment add constraint FK_se9l149iyyao6va95afioxsrl foreign key (comments_id) references comment][]}
Query:{[alter table post_comment add constraint FK_6o1igdm04v78cwqre59or1yj1 foreign key (post_id) references post][]} #insert post in primary transaction
Query:{[insert into post (name, version, id) values (?, ?, ?)][Hibernate training,0,1]} #select post in secondary transaction
Query:{[select entityopti0_.id as id1_1_0_, entityopti0_.name as name2_1_0_, entityopti0_.version as version3_1_0_ from post entityopti0_ where entityopti0_.id?][1]}
Query:{[select comments0_.post_id as post_id1_1_0_, comments0_.comments_id as comments2_2_0_, entityopti1_.id as id1_0_1_, entityopti1_.post_id as post_id3_0_1_, entityopti1_.review as review2_0_1_, entityopti2_.id as id1_1_2_, entityopti2_.name as name2_1_2_, entityopti2_.version as version3_1_2_ from post_comment comments0_ inner join comment entityopti1_ on comments0_.comments_identityopti1_.id left outer join post entityopti2_ on entityopti1_.post_identityopti2_.id where comments0_.post_id?][1]} #insert comment in secondary transaction
Query:{[insert into comment (id, review) values (default, ?)][Good post!]}
Query:{[insert into post_comment (post_id, comments_id) values (?, ?)][1,1]} #update works in primary transaction
Query:{[update post set name?, version? where id? and version?][Hibernate Master Class,1,1,0]}结论 了解各种建模结构如何影响并发模式非常重要。 递增父版本号时将考虑拥有方集合的更改您始终可以使用OptimisticLock批注来绕过它。 代码可在GitHub上获得 。 翻译自: https://www.javacodegeeks.com/2014/11/hibernate-collections-optimistic-locking.html