First of all I will explain why I would like to manually set write locks. I use Neo4j database in my web service application based on Spring Data Neo4j. Transactions are managed by Spring, I just use @Transactional annotation. However, I have problem with specific use case which leads to database inconsistency. I have a method that is transactional and its aim is to make such nodes/relation in database:
(p:Person)-[:USES]->(s:SIM_Card{phoneNumber:"xxx"})
Its algorithm is as follows:
-check if there is a SIM_Card with specific phone number (unique) already in the database (cypher query through @Query),
-if yes get this node and if no create it,
-check if there is any Person attached to this SIM_Card with USES relation (cypher query),
-if there is no such Person create it and attach to SIM_Card.
Unfortunately when there are many requests it happens that I have in database SIM_Cards that are attached to more than one Person. I assume that method is executed by two concurrent threads. Both read database and search for SIM_Card with the same phone number, and both get the information that there is no such SIM_Card in database yet, so they create them, and then they attach two separate Person to them. PhoneNuber is unique for SIM_Card, so eventually there is only one SIM_Card, but two Person remains and it is not expected situation. To fix this I would like to create SIM_Card in separate Transaction and then create Person and attach to this SIM_Card in another transaction. Before the Person is created I will check if there is no Person already attached. However, just before that check I would like to set a write lock manually on SIM_Card and I assume that then other Transaction would not be able to check in meantime if there is/or not any Person connected to this SIM_Card. It would have to wait for the lock to be released and then it will see that this SIM_Card has Person attached and would not create another one.
To achieve that I have to get somehow ability to set Neo4j locks inside @Transactional annotated method and I do not know how to do that. I would really appreciate your help.
@Transactional
hasisolation
attribute which would possibly help. But unfortunately,Neo4jTransactionManager
throws exception indoBegin()
method if this setting deviates from default: github.com/spring-projects/spring-data-neo4j/blob/master/… – PAX