简体   繁体   English

使用session.save保存对象时,Hibernate不会刷新会话?

[英]Hibernate does not flush session when save object using session.save?

First of all take a look at below code, I have three main model to manage StoreHouse and StoreHouseInvetory 's and have other model named StoreHouseInventoryLock to temporary lock/unlock some amount of StoreHouseInvetory 's when other processes wants to use these models: 首先看下面的代码,我有三个主要模型来管理StoreHouseStoreHouseInvetory ,还有其他名为StoreHouseInventoryLock模型可以在其他进程想要使用这些模型时临时锁定/解锁一定数量的StoreHouseInvetory

public class StoreHouse {
    private String  name;
    private Double  currentAmount;
}

public class StoreHouseInventory {
    private StoreHouse  storeHouse;
    private Good        good;
    private Double      amount;
}

public class StoreHouseInventoryLock {
    private StoreHouseInventory     inventory;
    private Double                  amount;
}

@Service
public class PermitService implements IPermitService {

    @Autowired
    private IStoreHouseInventoryLockService storeHouseInventoryLockService;

    @Autowired
    private IStoreHouseService storeHouseService;

    @Override
    @Transactional
    public void addDetailToPermitFromStoreHouseInventory(long permitId, long storeHouseId, long inventoryId, double amount) {

        // do some business logic here

        /* save is simple method
         * and uses Session.save(object)
        */
        storeHouseInventoryLockService.add(inventoryId, +amount);

        // do some business logic here
        storeHouseService.syncCurrentInventory(storeHouseId);   
    }
}

@Service
public class StoreHouseService implements IStoreHouseService {

    @Autowired
    private IStoreHouseInventoryService storeHouseInventoryService;

    @Autowired
    private IStoreHouseInventoryLockService storeHouseInventoryLockService;

    @Transactional
    public void syncCurrentInventory(storeHouseId) {
        /* is a simeple method that use query like below
         * select sum(e.amount)
         *   from StoreHouseInventory
         *  where e.storeHouse.id = :storeHouseId
         */
        Double sumOfInventory = storeHouseInventoryService.sumOfInventory(storeHouseId);
        /* is a simeple method that use query like below
         * select sum(e.amount)
         *   from StoreHouseInventoryLock
         *  where e.storeHouseInventory.storeHouse.id = :storeHouseId
         */
        Double sumOfLock = storeHouseInventoryService.sumOfLock(storeHouseId);

        // load method is a simple method to load object by it's id
        // and used from Session.get(String entityName, Serializable id)
        StoreHouse storeHouse = this.load(storeHouseId);
        storeHouse.setCurrentAmount(sumOfInventory - sumOfLock);

        this.save(storeHouse);
    }
}

the problem is that when storeHouseInventoryService.sumOfLock is called in StoreHouseService.syncCurrentInventory , it does not be aware change of storeHouseInventoryLockService.add method in PermitService.addDetailToPermitFromStoreHouseInventory method, and calcuates sum of locks incorrectly. 问题是,当在storeHouseInventoryService.sumOfLock中调用StoreHouseService.syncCurrentInventory ,它不知道storeHouseInventoryLockService.add方法中PermitService.addDetailToPermitFromStoreHouseInventory方法的更改,并且错误地计算了锁的总和。

I think this is because of session was not flushed when I call storeHouseInventoryLockService.add . 我认为这是因为在我调用storeHouseInventoryLockService.add时未刷新会话。 If it's true, why hibernate does not flsuh session during this changes? 如果是真的,为什么在此更改期间休眠不休眠会话? If not, what should I do? 如果没有,我该怎么办?

As IStoreHouseInventoryLockService.add is called from within a method which already has a transaction attached to it, then the same transaction is propagated to the add method, thus the flush does not happen until the outer addDetailToPermitFromStoreHouseInventory finishes. 由于从已附加事务的方法中调用IStoreHouseInventoryLockService.add ,因此将同一事务传播到add方法,因此直到外部addDetailToPermitFromStoreHouseInventory完成后才进行addDetailToPermitFromStoreHouseInventory

A quick solution for you would be to mark the add method with a REQUIRES_NEW transaction propagation type: 一个快速的解决方案是将add方法标记为REQUIRES_NEW事务传播类型:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void add(..){..}

Now after that method finishes, even though there is an outer transaction, all the persistence changes will be flushed to the database on exit. 现在,该方法完成后,即使存在外部事务,所有持久性更改也将在退出时刷新到数据库。

如果当前正在执行的查询与未刷新的表语句不重叠,则可以安全地忽略刷新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM