Hello,
I’m experiencing a data consistency issue where changes saved via DataManager are not visible when immediately querying with JmixDataRepository in the same transaction.
Issue
I have two services that run sequentially within the same @Transactional method:
Service 1 - SalesOrderService (saves entity with DataManager):
@Component
public class SalesOrderService {
private final DataManager dataManager;
private final BillingService billingService;
@Transactional
public void computeTimerItems(SalesOrder salesOrder) {
// ... load items and process ...
for (SalesOrderItem currentItem : activeItems) {
// simplified logic
currentItem.updateTimer();
// Save with DataManager - qty is now 74
dataManager.save(currentItem);
System.out.println("After DataManager.save() - qty: " + currentItem.getQty()); // Outputs: 74
}
// Immediately call billing service
billingService.computeTimerItems(salesOrder);
}
}
Service 2 - BillingService (queries with JmixDataRepository):
@Component
public class BillingService {
private final SalesOrderItemRepository salesOrderItemRepository;
private final DataManager dataManager;
@Transactional
public void computeTimerItems(SalesOrder salesOrder) {
// Query via repository - gets OLD value (33) instead of 74
List<SalesOrderItem> activeBillings = salesOrderItemRepository
.findTimerBillingBySalesOrder(salesOrder.getId());
System.out.println("After repository query - qty: " + activeBillings.get(0).getQty()); // Outputs: 33 (stale data!)
// ... rest of billing logic uses incorrect qty value ...
}
}
Repository definition:
@Repository
public interface SalesOrderItemRepository extends JmixDataRepository<SalesOrderItem, UUID> {
@Query("select e from repos_SalesOrderItem e where e.saleOrder.id = :salesOrderId " +
"and e.timerStarts is not null and e.previousSalesOrder is null")
List<SalesOrderItem> findTimerBillingBySalesOrder(@Param("salesOrderId") UUID salesOrderId);
}
What’s Happening
- DataManager.save() updates qty to 74 and marks it dirty in the persistence context
- JmixDataRepository query executes immediately and retrieves 33 from the database
- The changes haven’t been flushed yet, so the repository sees stale data
- NOTE that the stale data happened on occasions (sometimes it works, sometimes it doesn’t)
Questions
- Is this expected behavior? Does DataManager.save() not automatically flush changes within a transaction?
- What’s the recommended approach? Should I:
- Use EntityManager.flush() after DataManager.save()?
- Replace the repository query with DataManager.load() for consistency?
- Use SaveContext with specific flush settings?
- Best practices: When mixing DataManager and JmixDataRepository in the same transaction, what should I be aware of regarding persistence context visibility?
Environment
- Jmix version: 2.5.2
Any guidance on the correct pattern would be greatly appreciated!