I have a situation, where data has concurrency in transaction.
Example: User 1 create Transaction 1 with Item 1 qty 3 and Item 2 qty 5. User 2 create Transaction 2 with Item 1 qty 6 and Item 2 qty 7.
Every Item has each their own balance (like in warehouse, item in and out).
How can I prevent concurrency that item balance from item 1 and item 2 count correctly, if transaction 1 and transaction 2 run in the same time from diffrence users?
Item 1 should has balance 9 (3 + 6), not 3 or 6, because of overwrite. Item 2 should has balance 12 (5 + 7).
I had experience in ColdFusion. When I used function cftransaction, every sql query will lock data and table (not all table, only in cftransaction) until commit or rollback called (correct me if I misunderstand).
What until now I apply:
In persistence.xml
<property name="eclipselink.session.customizer"
value="com.sft.FlexiSessionCustomizer" />
In java file:
public class FlexiSessionCustomizer implements SessionCustomizer {
@Override
public void customize(Session session) throws Exception {
DatabaseLogin databaseLogin = (DatabaseLogin) session
.getDatasourceLogin();
databaseLogin
.setTransactionIsolation(DatabaseLogin.TRANSACTION_SERIALIZABLE);
}
}
Insert method (it's pure insert to database):
public boolean insertDataBean(Object data) {
if (data == null) {
logger.error("Data is not valid.");
return false;
}
boolean result = true;
EntityManager em = this.createEntityManager();
data.setCreatedDate(new Timestamp((new Date()).getTime()));
EntityTransaction entr = em.getTransaction();
try {
entr.begin();
em.persist(data);
entr.commit();
} catch (Exception e) {
logger.error("ERROR INSERT : " + data.getClass().getName() + " | "
+ e.getMessage());
result = false;
}
em.close();
return result;
}
Call the insert method:
insertDataBean(transaction1); // from user 1
insertDataBean(transaction2); // from user 2
Is that enough to prevent concurrency?
What I think, maybe, I should change the insert code like:
public boolean insertDataBean(Object data) {
if (data == null) {
logger.error("Data is not valid.");
return false;
}
boolean result = true;
EntityManager em = this.createEntityManager();
data.setCreatedDate(new Timestamp((new Date()).getTime()));
EntityTransaction entr = em.getTransaction();
try {
entr.begin();
// all code, like read item balance and calculation item balance?
// should query use the same entity manager (em) or new entity manager will be the same?
em.persist(data);
// Other code transaction
entr.commit();
} catch (Exception e) {
logger.error("ERROR INSERT : " + data.getClass().getName() + " | "
+ e.getMessage());
result = false;
}
em.close();
return result;
}
Do I still need to appy Pessimistic-locking?
Maybe someone can help me, to prevent the concurrency in transactions?
Thank you in advance.