Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在没有字段更改的情况下,如何在hibernate中使用乐观锁_Hibernate_Versioning_Optimistic Locking - Fatal编程技术网

在没有字段更改的情况下,如何在hibernate中使用乐观锁

在没有字段更改的情况下,如何在hibernate中使用乐观锁,hibernate,versioning,optimistic-locking,Hibernate,Versioning,Optimistic Locking,当通过在hbm.xml s中设置元素来更新实体时,我使用的是乐观策略。当我更新单个实体时,它工作正常。但这种策略在处理这种情况时失败了: public class SalesPlan { //omitted fields private Resource resource; private DateRange dateRange; } public class Resource { //omitted fields private int versio

当通过在hbm.xml s中设置元素来更新实体时,我使用的是乐观策略。当我更新单个实体时,它工作正常。但这种策略在处理这种情况时失败了:

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


public class Resource {
    //omitted fields
    private int version = 1;
}
还有一个约束:资源不应具有日期范围重叠的销售计划。例如:

这里有一个名为Hippoom resort的资源

其销售计划范围为2013年11月1日至2013年11月2日

当我想添加2013年11月2日至2013年11月2日的销售计划时

那么对于重叠的日期范围,它应该失败

我必须用Java实现这一点,因为数据库唯一键在这种情况下不起作用。代码如下所示:

@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;
}
我从重复SalesPlanSpecification中的数据库中获取所有现有的SalesPlan,以检查新的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 ------修改--------

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 

Hibernate版本是3.6.10.FINAL。我有没有可能解决这个问题?

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

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

    private boolean dirty = false;

    public void alwaysMakeDirty() {
        this.dirty = !dirty;
    }
}
这个字段在域中没有任何意义,但是在我更新资源之前,我可以使用AlwaysMaxDirty启动更新sql


我知道这很棘手,但它很有效。

试试em。Lock类、primaryKey、LockModeType和


LoMyDyType .Posiv-这是一个在事务结束时检查版本的情况,如果有人在中间改变它,并最终回滚或LoopMoDyType。Opdate IsPixFuffelPosith-这个总是在事务结束时更新并检查版本,如果必须从你的代码中翻转,我就看不到任何版本。您对SalesPlan或资源实体所做的更改。所以,除非有更多的代码,然后请张贴它没有理由更新,因为没有任何变化。对不起,我没有说清楚。我想保存销售计划并检查资源是否未被其他人修改。请查看修改后的帖子内容。为什么您不使用HQL来解决此问题,而不尝试在实体中修复它?@BeenCoding2Long:对不起,我不明白。你能给我看一些示例代码吗?我想要这个更新,以防其他人想同时添加新的销售计划。这将破坏验证,因为大多数数据库只能读取提交的数据。