2013-05-28 35 views
1

通过在hbm.xml中设置"<version />"元素来更新实体时,我使用乐观策略。当我更新单个实体时它工作正常。如何在没有字段更改的情况下使用乐观锁休眠

public class SalesPlan { 
    //omitted fields 
    private Resource resource; 
    private DateRange dateRange; 
} 


public class Resource { 
    //omitted fields 
    private int version = 1; 
} 

,并有一个约束::一个资源应该不会有SalesPlan s的重叠dateRange.For例如:

假设有一个但这种情况时,这策略失败资源名为 “Hippoom胜地”

而且它有一个SalesPlan,从2013年11月1日至2013年11月2日

当我想添加一个SalesPlan,从2013年11月2日至2013年11月2日

那么就应该失败重叠的日期范围

我要实现这在Java中,因为数据库中唯一关键并不在这个“范围” case.The代码的工作是这样的:

@Transactional 
@Override 
public SalesPlan handle(CreateSalesPlanCommand command) { 
    Resource resource = resourceRepository.findBy(command.getResourceId()); 
    SalesPlan salesPlan = //omitted init codes 

    DuplicateSalesPlanSpecification spec = aDuplicateSpec(); 

    if (spec.isSatisfiedBy(salesPlan)) { 
     throw new DuplicateSalesPlanException(salesPlan); 
    } 

    salesPlanRepository.store(salesPlan); 
    resourceRepository.store(salesPlan.getResource()); 
    return salesPlan; 
} 

我获取所有在存在SalesPlan■从数据库DuplicateSalesPlanSpecification来检查新的SalesPlan是否违反了约束条件。我想在最后一步(检查资源中的版本号)时更新资源以防并发操作。但我注意到没有更新的SQL,因为资源不脏。

------修订--------

select 
    resource0_.RESOURCE_ID as RESOURCE1_0_0_, 
    resource0_.version as version0_0_, 
    //omitted columns 
from 
    T_IRS_RESOURCE resource0_ 
where 
    resource0_.RESOURCE_ID=? 


select 
    this_.SALES_PLAN_ID as SALES1_1_0_, 
    this_.version as version1_0_, 
    this_.RESOURCE_ID as RESOURCE3_1_0_, 
    this_.DATE_RANGE_START as DATE4_1_0_, 
    this_.DATE_RANGE_END as DATE5_1_0_, 
    //omitted columns 
from 
    T_IRS_SALES_PLAN this_ 
where 
    this_.RESOURCE_ID=? 
order by 
    this_.DATE_RANGE_START desc, 
    this_.SALES_PLAN_ID desc 


insert into T_IRS_SALES_PLAN//omitted columns 


update T_IRS_RESOURCE set version = version + 1 
where RESOURCE_ID = ? 
and VERSION = ?   //this sql missed 

在使用乐观策略,SalesPlan获取SQL可能是过时的,如果有人插入另一交易新SalesPlan没有最后SQL

 
| the first transaction started    | 
|            | the second transaction started 
| select resource        | 
|            | select resource 
| select all salesplans      | 
|            | select all salesplans 
| validate base on all committed salesplans | 
|            | validate base on all committed salesplans 
| insert salesplan       | 
|            | insert salesplan 
| update resource to check version   | 
|            | update resource to check version 
| commit txn         | 
|            | rolls back because version is dirty 

------修订--------

Hibernate的版本是3.6.10.FINAL.Is有任何可能性我在f这是什么?

+0

从您的代码中,我看不到您对SalesPlan或Resource实体所做的任何更改。所以,除非有更多的代码(然后请张贴它),没有理由更新,因为没有更改。 –

+0

对不起,我没有说清楚。我想保存“SalesPlan”并检查“资源”是否未被其他人修改。请参阅修改后的内容。 – Hippoom

+0

为什么你不使用HQL进行约束而不是试图在实体中修复它? –

回答

0

我找到了一个临时解决方案。我的资源添加一个布尔字段,如:

public class Resource { 
    //omitted fields 
    private int version = 1; 

    private boolean dirty = false; 

    public void alwaysMakeDirty() { 
     this.dirty = !dirty; 
    } 
} 

此字段并不意味着在任何领域,但在此之前我更新的资源,我可以使用alwaysMakeDirty()来触发更新SQL。

我知道这很棘手,但它的工作原理。

0

尝试em.Lock(类的PrimaryKey,LockModeType)与

LockModeType.OPTIMISTIC - 这一个检查事务的最后版本的情况下,有人在中间,最后卷更改它返回或LockModeType。OPTIMISTIC_FORCE_INCREMENT - 这个总是在交易结束时更新和检查版本,如果必要的话回滚版本

相关问题