我知道,当覆盖hashcode()和equals()我的持久化实体的我不应该包括ID,只包括有意义的属性唯一标识对象.但是Hibernate version用于乐观并发控制的字段呢?我应该跳过它,就像ID一样吗?如果让我们说new User(name='John', version=1).equals(new User(name='John',version=2)),不管怎么说它不会混淆Hibernate OCC呢?
hibernate version hashcode optimistic-locking optimistic-concurrency
我正在尝试按顺序实现乐观锁定以避免丢失更新情况.在我的应用程序中,两个用户获取相同的记录,第一个用户通过一些更改更新它.查看相同记录的第二个用户看不到此更改,他自己进行了一些更改并对其进行了更新.由此导致第一批人员失去了.为了防止这种情况,我写了以下内容,但问题仍然存在.我是这个概念的新手,无法识别问题.
我试图通过阅读doc 11.3.4 来实现这一目标.自定义自动版本控制部分.
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<value>server.bo.Dept</value>
<value>server.bo.Emp</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<bean id="deptDAO" class="server.dao.DeptDAOImpl">
<property …Run Code Online (Sandbox Code Playgroud)我在检查NHibernate的日志文件时,发现了一些随机错误,如下:
NHibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MaltaIndependent.Modules._AutoGen.MemberImpl#353796206]
at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session) in c:\Repository\Work\CodeBase\C#\+OpenSource\nHibernate\nhibernate-core-master-v3.3.1\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:line 2821
at NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session) in c:\Repository\Work\CodeBase\C#\+OpenSource\nHibernate\nhibernate-core-master-v3.3.1\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:line 2702
at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object …Run Code Online (Sandbox Code Playgroud) 嗨,我有以下senario,我不明白如何获得最终的一致性:
如果我们在事件中传递聚合的版本,那么在13中会出现乐观的并发错误吗?
如果是,则将消息1新应用于其他上下文中的对象.我们如何保持一致性?
这是阻止我在我的域中应用事件的问题.欢迎所有帮助.
基本思想是在另一个上下文中更新另一个聚合.我只是坚持这个并发技术.
我们不是在命令处理程序和命令推送总线的意义上使用事件源或CQRS.只有事件处理我们想要异步发生,因为我们有一个我们不希望改变的现有设计.
布莱尔
domain-driven-design event-handling eventual-consistency optimistic-locking domain-events
当使用乐观锁定策略时,它可以解决如下的并发问题:
| the first transaction started | | | | select a row | | | the second transaction started | update the row with version checking | | | select the same row | commit txn | | | update the row with version checking | | | | rolls back because version is dirty
但是,如果在极少数情况下,第二个事务中的更新是在第一个事务中的udpate之后但是在事务提交之前呢?
| the first transaction started | | | the second transaction started | select a row | | | select the same row …
我有以下
def save(ACommand command){
...
}
@Validateable
class ACommand implements Serializable
{
ADomainObject bundleDef
}
Run Code Online (Sandbox Code Playgroud)
但每次 save 被调用时,版本都会增加。因此,如果我打开两个浏览器并连续提交不同的值,而不是像我预期的那样第二次出错,而是更新了值。
我也尝试使用两个不同的会话没有区别
更新
如果我使用断点并在另一个断点完成之前提交它工作正常。但是,如果我让第一个完成,然后在不刷新的情况下提交第二个,则版本将更新为较新的(我不想要的)并且更改会通过。
更新 2
当您执行更新时,Hibernate 将自动根据数据库中的 version 列检查 version 属性,如果它们不同,将抛出 StaleObjectException。如果事务处于活动状态,这将回滚事务。
每个 Grails这在我看来应该有效。
EJB 中使用 CMT 的事务方法可删除提供的实体:
public boolean delete(Entity entity) {
Entity managedEntity = entityManager.find(Entity.class, entity.getId());
if (managedEntity == null) {
throw new EntityNotFoundException();
}
entityManager.remove(managedEntity);
return !entityManager.contains(managedEntity);
}
Run Code Online (Sandbox Code Playgroud)
关联的客户端提供的实体是分离的实体。该entityManager.remove()操作生成DELETE如下 DML 语句:
public boolean delete(Entity entity) {
Entity managedEntity = entityManager.find(Entity.class, entity.getId());
if (managedEntity == null) {
throw new EntityNotFoundException();
}
entityManager.remove(managedEntity);
return !entityManager.contains(managedEntity);
}
Run Code Online (Sandbox Code Playgroud)
如果数据库中的行版本与实体中的行版本冲突,则附加检查AND (version = ?)应导致抛出 。javax.persistence.OptimisticLockException
javax.persistence.OptimisticLockException然而,即使提供的实体要在另一个会话中由另一个用户同时修改,这也不会抛出异常,因为它是由客户端(Web 或其他方式)最后读取的,因为该find()方法在另一个事务中获取具有更新的行版本的实体(旧的/过时的行版本(由 标记@javax.persistence.Version)仅包含在作为方法参数提供的分离实体中)。
与 不同的是EntityManager#merge(T entity),EntityManager#remove(Object entity) …
客户端应用程序提供了一个陈旧的实体,该实体将被 Hibernate 合并。举个很简单的例子。
public Entity update(Entity entity) {
return entityManager.contains(entity) ? entity : entityManager.merge(entity);
}
Run Code Online (Sandbox Code Playgroud)
Entity例如,是由 Web 应用程序提供的分离的、陈旧的实体。该方法在活动的 JTA 事务(或本地资源)中执行。
乐观锁已通过引入 @Version在给定的实体中字段,。
当要合并的实体已经被删除时,javax.persistence.OptimisticLockException预计会抛出这不会发生的情况。Hibernate 执行INSERT,这是完全出乎意料的。插入一个陈旧的实体而不是抛出javax.persistence.OptimisticLockException是有悖于锁定的。
“插入或更新”是一个分开的故事,应该通过抛出 javax.persistence.OptimisticLockExceptionmerge(),如果实现了乐观锁定,如果过时或已删除(不存在)的实体被传递给。
javax.persistence.OptimisticLockException如果过时或已删除/不存在的实体被传递给,EclipseLink 会按预期抛出merge()。
javax.persistence.OptimisticLockException当一个陈旧或不存在的实体被传递给时,有没有办法让 Hibernate 抛出,merge()?
我希望应该有一些可配置的属性 persistence.xml全局应用程序范围内应用它,或者使用注释将它应用到特定实体。
我目前使用的是 Hibernate 5.0.5 final。
更新到 Hibernate 5.0.6 最终版。
众所周知,有两种锁定策略:乐观锁定与悲观锁定
悲观锁定是当您锁定记录以供您独占使用,直到您完成它为止。它比乐观锁具有更好的完整性,但要求您在应用程序设计时要小心以避免死锁。
还知道,乐观并发控制与多版本并发控制(Oracle 或 MSSQL-Snapshot/MVCC-RC)不同:乐观与多版本并发控制 - 差异?
但是如果在两个事务中都使用 OCC(乐观并发控制),是否会在两个事务之间发生死锁?
我们能说乐观锁通过降低一致性来降低死锁的可能性吗?并且只有当每个更新都在一个单独的事务中时,死锁的可能性才为 0%,但这样的一致性最小。
sql-server oracle locking optimistic-locking pessimistic-locking
我需要我的应用程序具有以下行为:
场景1
用户A查看订单。
用户B查看相同的订单。
场景2
使用 JPA(Hibernate via Spring Data JPA),我尝试用来@Version实现这种乐观锁定行为:
@Entity
public class Order {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Version
private Integer version;
// many other fields
Run Code Online (Sandbox Code Playgroud)
删除时,UI 客户端向服务器提供订单 ID 列表以及每个订单 ID 的版本号。这篇文章(Spring Data JPA:删除乐观锁定语义)提到了一个标准解决方案:
if (entity.getVersion() != dto.getVersion()) {
throw new OptimisticLockException("...");
}
Run Code Online (Sandbox Code Playgroud)
要使用这个,我必须
问题是在步骤 2 中实体和 DTO 版本可能相同。但到了第3步,版本可能会有所不同。有没有办法让 hibernate 作为单个原子操作执行检查和更新,例如:
delete from [Order] where orderId = ? …Run Code Online (Sandbox Code Playgroud) hibernate ×5
jpa ×3
c# ×1
concurrency ×1
eclipselink ×1
grails ×1
grails-orm ×1
hashcode ×1
locking ×1
merge ×1
nhibernate ×1
oracle ×1
spring ×1
sql-server ×1
version ×1