2016-09-04 18 views
1

我在我的服務層有一些業務檢查,我在那裏查詢一些查詢和條件。如何保證事務服務方法中的行級唯一約束?

他們不能在數據庫層做一個獨特的或檢查。但併發中兩個請求通過檢查並在我的數據中出錯。 問題是:我從用戶控件中取出商品序列,並且如果數據庫中不存在與數據庫串行檢查商品讓它保存記錄,否則拋出異常。 圖像有助於理解這個問題更好: http://pasteboard.co/gPE0BRlRK.jpg

我們可以使用休眠悲觀鎖,但如果我們沒有任何記錄在數據庫號A100例如抽查合格並在數據庫中的兩個事務提交。

保存方法是在這裏:

@Override 
    public Long save(Product entity) { 
     if (!isUniqueForSave(entity)) 
      throw new ApplicationException(saveUniqueError); 
     return super.save(entity); 
    } 

和方法isUniqueForSave:

private boolean isUniqueForSave(Product entity) { 
      return iProductRepository.isUniqueForSave(entity); 
     } 

和DAO層的查詢是這個方法:

public boolean isUniqueForSave(Product entity) { 

     Session session = getSession(); 
     String hql = "select c from " + domainClass.getName() + " c " 
        + " where c.ProductNumber  = :productNumber " 
        + " and c.item.id = :itemId " 
        + " and c.deleted  = 0 "; 



     if (entity.getId() != null && entity.getId() > 0) 
      hql += " and c.id != "+entity.getId(); 

     Query query = session.createQuery(hql); 
     query.setParameter("productNumber ", entity.getProductNumber()); 
     query.setParameter("itemId ", entity.getItem().getId()); 

     List<Product> productsList = query.list(); 
     if(productsList .size() > 1) 
      return false; 
     else if(productsList .size() == 0) 
      return true; 

     Product product= productsList .get(0); 
     if(entity.getOldItem() != null && product.getId().equals(entity.getOldItem().getId())) 
      return true; 

     return false; 

    } 
+0

是否要保存具有唯一ID的訂單?目前還不清楚你在問什麼。 –

+0

我想要保存一個貨物,貨物序列必須唯一,我不能在數據庫上做它,我必須在業務檢查中做到這一點服務層 –

+0

我這樣做的方式,運行這樣的查詢:select * from貨物e where suchoodsNumber =:goodsNumber和goosCode =:goodsCode和e.delete = 0 –

回答

1

你的代碼是容易受SQL注入影響。你真的想要修好它!

這裏的問題是,你想保證沒有其他交易會偷偷進來,並添加一個Product具有相同的過濾標準。

如果數據庫中已有一行,樂觀鎖定只能幫助您。因此,就你而言,樂觀鎖定僅適用於該行被標記爲已刪除的情況。

但是,即使查詢執行時數據庫中沒有記錄,也希望此檢查工作正常。在這種情況下,you need to use SERIALIZABLE,因爲它可以防止幻影讀取和丟失更新。

您需要將當前事務標註爲Serializable。退房this article for more info on this topic

+0

SERIALIZABLE如何防止幻像讀取? –

+0

閱讀我在答案中提供的文章。有關更詳細的說明,可以查看我的[高性能Java持久性](https://leanpub.com/high-performance-java-persistence)書。 –