2013-03-05 48 views
1

我收集了一些关于我的系统的日统计数据,比方说,使用我系统的人数和他们今天花费的总时间。我的统计实体是这样的:根据以前的值原子插入或更新实体

class Stats { 
    Date date; 
    Long numUsers; 
    Long totalTime;   
} 

白天我需要更新这些统计基于先前值,如:

stats.numUsers += 1; 
stats.totalTime += timeSpentByLastUser; 

当然,如果这是第一次对于今天,我需要初始化这些数据:

stats.numUsers = 1; 
stats.totalTime = timSpentByFirstUserForToday; 

现在我想将全部移到数据库。也就是说,使Stats成为一个实体并根据先前的值进行原子插入/更新。那么,我该如何做到这一点?我正在使用JPA,因此适合其型号的任何解决方案都将适用。

请注意,JPA具有插入或更新机制 - EntityManager.merge() - 但它没有考虑实体的先前状态,这在此处是必需的。

+0

如果DB是ACID则交易已经原子,所有你需要的要做的是[锁定数据](http://city81.blogspot.co.uk/2011/03/pessimistic-and-optimistic-locking-in.html)。 – 2013-03-05 14:15:14

+0

目前我们使用2个保存ACID属性的数据库,但它可能会改变,所以我正在寻找一个基于JPA的解决方案(我假定JPA并不保证底层数据库始终保持ACID)。 – ffriend 2013-03-05 14:25:34

回答

3

是的,你保持原子性,通过强制用于持久化的事务锁定机制。

Employee employee = entityManager.find(Employee.class, id); 
employee.getAddress().setCity("Ottawa"); 
entityManager.lock(employee, LockModeType.WRITE); 

请参考下面的链接,它提供了JPA可用的锁模式2.0

JPA 2.0 Locking