2017-02-21 10 views
2

Прежде всего, посмотрите на код ниже, у меня есть три основные модели для управления StoreHouse и StoreHouseInvetory и имеют другую модель с именем StoreHouseInventoryLock для временного блокирования/разблокировки некоторого количества StoreHouseInvetory, когда другие процессы хотят использовать эти модели:Hibernate не очищает сессию при сохранении объекта с помощью session.save?

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); 
    } 
} 

проблема заключается в том, что, когда storeHouseInventoryService.sumOfLock вызывается в StoreHouseService.syncCurrentInventory, он не будет знать, изменение storeHouseInventoryLockService.add метода в PermitService.addDetailToPermitFromStoreHouseInventory метода и calcuates сумма замков неправильно.

Я думаю, что это из-за сеанса не сработало, когда я звоню storeHouseInventoryLockService.add. Если это правда, почему спящий режим не выполняет сеанс flsuh во время этих изменений? Если нет, что мне делать?

+0

Для начала кода вы ошибаетесь, вы никогда не должны ломать исключения и проглатывать, ваш код нарушает правильное управление tx. Данные видны из одной транзакции, а спящий режим автоматически отключает ожидающие изменения при приостановке базы данных. Если этого не произойдет, вы, вероятно, делаете что-то вокруг задней части спящего режима. Добавьте код для метода синхронизации (и связанных объектов). –

+0

Извините, это была моя ошибка, я удалил блок 'try, catch' –

ответ

0

В IStoreHouseInventoryLockService.add вызывается из метода, который уже имеет сделку, прикрепленный к нему, то тот же транзакции распространяется к методу add, таким образом, на одном уровне не происходит до тех пор, наружных addDetailToPermitFromStoreHouseInventory отделки.

Быстрое решение для вас было бы отметить add метод с REQUIRES_NEW типом распространения транзакции:

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

Теперь после того, как этот метод заканчивается, даже если есть внешняя транзакция, все изменения инерционности будут покраснел в базу данных при выходе.

+0

В той же транзакции данные уже видны, для этого вам не нужна новая транзакция. Если данные не видны, происходит что-то еще. –

+0

@ M.Deinum, вы имеете в виду, что нет необходимости использовать '@Transactional (распространение = Propagation.REQUIRES_NEW)'? Как я могу решить эту проблему? –

+0

Во время запроса в методе sumOfLock .. возможно, изменения не сбрасываются в базу данных непосредственно перед вызовом. Теоретически да, они должны быть, если в запросе используются объекты, которые были затронуты в текущей транзакции. –

0

Если текущий исполняемый запрос не перекрывается с операторами нефиксированной таблицы, флеш можно безопасно игнорировать.

+0

https://vladmihalcea.com/2014/08/13/the-dark-side-of-hibernate-auto-flush/ –

Смежные вопросы