是否可以关闭特定更新的休眠版本增量?

Pal*_*ium 8 hibernate jpa

是否可以在不使用hibernate修改实体版本的情况下在数据库中更新实体?

使用我的Web应用程序,用户可以创建或更新实体.另外一个异步过程在任何用户操作之后"处理"这些实体.如果用户在"处理"实体之前打开实体进行更新,但在"处理"实体后尝试保存,则用户将获得"OptimisticLockException",并且所有输入的数据都将丢失.但我想用用户提供的数据覆盖异步过程中更新的数据.

代码snipet来演示为什么我需要这样的行为(JPA + Hibernate):

//user creates entity by filling form in web application
Entity entity = new Entity ();
entity.setValue("some value");
entity.setProcessed (false);
em.persist(entity);
em.flush();
em.clear();

//but after short period of time user changes his mind and again opens entity for update
entity = em.find(Entity.class, entity.getId());
em.clear(); //em.clear just for test purposes

//another application asynchronously updates entities 
List entities = em.createQuery(
                "select e from Entity e where e.processed = false")
                .getResultList();
for (Object o: entities){
    Entity entityDb = (Entity)o;
    someTimeConsumingProcessingOfEntityFields(entityDb); //update lots of diferent entity fields
    entityDb.setProcessed(true);
    em.persist(entityDb);
}        
em.flush(); //version of all processed entities are incremented.       
//Is it possible to prevent version increment?
em.clear();  

//user modifies entity in web application and again press "save" button
em.merge(entity); //em.merge just for test purposes
entity.setValue("some other value");
entity.setProcessed (false);
em.persist(entityDb);
em.flush(); //OptimisticLockException will occur.        
//Is it possible to prevent this exception from happening?
//I would like to overwrite data updated in asynchronous process 
//with user provided data.
Run Code Online (Sandbox Code Playgroud)

而我的实体:

@Entity
@Table(name = "enities")
public class Entity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Version
    private int versionNum;
    @Column
    private String value
    @Column
    private boolean processed;
    //… and so on (lots other properties)
}
Run Code Online (Sandbox Code Playgroud)

实际上我有更多类似问题的类 - 所以我正在寻找一些优雅的非侵入式解决方案.

在我看来,这是很常见的情况.但我找不到任何有关如何实现此类功能的信息.

Pal*_*ium 2

可以使用 hibernate Session ( http://docs.jboss.org/hibernate/orm/5.0/javadocs/org/hibernate/Session.html ) replicate(...)方法绕过 Hibernate 乐观锁定。

不增加版本的代码示例:

//Detaching to prevent hibernate to spot dirty fields. 
//Otherwise if entity exists in hibernate session replication will be skipped 
//and on flush entity will be updated with version increment.
em.detach(entityDb); 
someTimeConsumingProcessingOfEntityFields(entityDb);  

//Telling hibernate to save without any version modifications.
//Update hapends only if no newer version exists.
//Executes additional query DB to get current version of entity.
hibernateSession.replicate(entity, ReplicationMode.LATEST_VERSION);
Run Code Online (Sandbox Code Playgroud)

我认为这个解决方案比原生 SQL 更新更好,因为:

  • ORM 映射(注释或 *.hbm.xml)是使用(无需在本机查询中重复 Java 对象 <-> DB 表映射);
  • 无需手动执行flush(性能);
  • db 和 hibernate 缓存处于相同状态,无需从缓存中逐出实体(性能);
  • 并且您仍然拥有 ORM 提供的所有功能,例如乐观锁定等……;